关于HTTP协议和WEBSOCKET协议的介绍

因为LPC提供了socket功能,通过socket可以实现各种标准协议通信,这里整理一下HTTP和WEBSOCKET协议相关内容,方便需要的同学。

超文本传输协议(Hypertext Transfer Protocol -- HTTP/1.1):

WebSocket协议(The WebSocket Protocol):

HTTP Header Field Registrations:


HTTP

简单的说,HTTP协议就是WWW网站用到的协议,这是一个请求/响应协议:用户从客户端(浏览器)向服务器发送请求(输入网址),服务器收到请求后响应内容。

Http URL

正常用户是通过URL使用客户端(浏览器)向服务端发送请求,HTTP URL规范如下:

http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]

请求和响应是有规范格式的,这一切都由客户端和服务端转换处理了,用谷歌浏览器按F12打开开发者模式,访问 http://mud.ren

在网络控制台可以看到请求和响应的细节:

file

请求标头

GET / HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7,zh-TW;q=0.6
Cookie: pgv_pvi=7817427968; pgv_si=s1628448768; remember_admin_59ba36addc2b2f9401580f014c7f58ea4e30989d=eyJpdiI6IjFjNHlOZ2l5SC9ZelJCSzRoN2xoK0E9PSIsInZhbHVlIjoiNGluNWdaa2E2OVI3a1ppREFnK0pqMm9oOFZZc0dleWFxRkVsTXpWZnlGbDM3T3JSVkQ2UzFManBieXhuWERFQ3QxUy83djBucWtzcTlGckd2dThZd2NObzZNc2JvcWRmV0pQK2krWXFwNEJXUUl0Nk5ObTl1MWp3dU83WFNGRmZIWFlwaDJ3QnduaUJpMHJFRG9JMEthTDRtOUhrU21WUlRHcy9ib3VGZ3YzakhBTlZRRWhvSWcySHFBUVZBRzVNZGl3Tlpha1JRS0hKQkZjMlFMTWc5czJMNEttZUpzNXd5SnRWZ3dzUTBsRT0iLCJtYWMiOiJmMjkxN2ZjMTNjZTY0M2EzY2RhMzc2NDE0YTZmNGU3YmViYzQ4MGY4ZjhhYjMyZWM2ZWFiMDhlYWJjNjk0ODg4In0%3D; _ga=GA1.2.655527758.1605767714; io=EO9Wg0YOVgUMtjxjAAAB; Hm_lvt_5b97c97363890ad3134047bd30955ec5=1652513496; Hm_lpvt_5b97c97363890ad3134047bd30955ec5=1652832584
Host: mud.ren
Proxy-Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36

请求标头(request header)是客户端发给服务端的,看起来比较复杂,具体规范为:

    Request       = Request-Line              ; Section 5.1
                    *(( general-header        ; Section 4.5
                     | request-header         ; Section 5.3
                     | entity-header ) CRLF)  ; Section 7.1
                    CRLF
                    [ message-body ]          ; Section 4.3

可见下图:

file

请求的Request-Line格式:

Request-Line   = Method SP Request-URI SP HTTP-Version CRLF

Request-Line的方法(method)包括:

   Method         = "OPTIONS"                ; Section 9.2
                  | "GET"                    ; Section 9.3
                  | "HEAD"                   ; Section 9.4
                  | "POST"                   ; Section 9.5
                  | "PUT"                    ; Section 9.6
                  | "DELETE"                 ; Section 9.7
                  | "TRACE"                  ; Section 9.8
                  | "CONNECT"                ; Section 9.9
                  | extension-method
   extension-method = token

Request-Line的Request-URI包括:

   Request-URI    = "*" | absoluteURI | abs_path | authority

URI中*是直接请求服务器而不是具体资源,主要用在OPTIONS方法中,如:

   OPTIONS * HTTP/1.1

HTTP-Version最新版是2.0,但目前主要使用的是1.0和1.1,HTTP/1.1HTTP/1.0最核心的区别有二点:

  1. HTTP/1.1默认是长连接(Connection: Keep-Alive)
  2. HTTP/1.1的请求头必须包括Host字段(Host: host[:port])

注意:如果服务端没有绑定host,request-header的Host值为空。

请求中request-header可用字段如下:

   request-header = Accept                   ; Section 14.1
                  | Accept-Charset           ; Section 14.2
                  | Accept-Encoding          ; Section 14.3
                  | Accept-Language          ; Section 14.4
                  | Authorization            ; Section 14.8
                  | Expect                   ; Section 14.20
                  | From                     ; Section 14.22
                  | Host                     ; Section 14.23
                  | If-Match                 ; Section 14.24
                  | If-Modified-Since        ; Section 14.25
                  | If-None-Match            ; Section 14.26
                  | If-Range                 ; Section 14.27
                  | If-Unmodified-Since      ; Section 14.28
                  | Max-Forwards             ; Section 14.31
                  | Proxy-Authorization      ; Section 14.34
                  | Range                    ; Section 14.35
                  | Referer                  ; Section 14.36
                  | TE                       ; Section 14.39
                  | User-Agent               ; Section 14.43

响应标头

HTTP/1.1 200 OK
Content-Length: 12584
Access-Control-Allow-Origin: *
Cache-Control: no-cache, private
Connection: keep-alive
Content-Type: text/html; charset=UTF-8
Date: Wed, 18 May 2022 01:33:58 GMT
Keep-Alive: timeout=4
Proxy-Connection: keep-alive
Server: Microsoft-IIS/8.5
Set-Cookie: XSRF-TOKEN=eyJpdiI6Im1WK096TkM5aHFmRjFic1hGTTk2U2c9PSIsInZhbHVlIjoiTDl1MUFrY3NXbkpZb0ZRL2hlNUw5QkJkUzlTWHhXZUt5MlMyYi9EbmFnVjluTEZEWTNGa2hNMDI4MG10S3hYZE14Zi9xOEJOTHcydGJTTDF3NGxEOGoyUUZuaUdiM204TllLTWo1aE84UHZPZ2J5SS9kN3Q5TzAyU0ZBaW1FUGoiLCJtYWMiOiJiY2FjZjMwZWE5YWVlMTE4ZmZkNTM3NzcwMDc0NjVlMGExOGM3NGU1MmRiMTJkZWM0NDlmMzcxNzQxZmJkOWM2IiwidGFnIjoiIn0%3D; expires=Wed, 18-May-2022 03:33:58 GMT; Max-Age=7200; path=/; samesite=lax
Set-Cookie: mudren_session=eyJpdiI6IkJYUUZ3Z2M5bHM4UkxVS1JEVEtsWmc9PSIsInZhbHVlIjoiSThmRDZaQkJ5bDFHRjkxOEhPOHdSM05tSEU2b0tLbEJEemFjbFNlU0wwbTV1Y0dJY3dqSzJlak8yVVR3NjNNSllpNEpxRm4zbHcyeVRzbmR1MGZMbjdNVVp4Z2NKd2hsTldUZDZJbnp0akF2ZXc0Tnhpc2M4Q1VkSnpTc050Zm4iLCJtYWMiOiJlN2RmYWQzOTgwYThiNDhlYzA3YTcwZDUwYmRlMGYzNGRjMTZhYjZhMTcwNjIzNDdkM2FhOWZkMjljMjNlYTRlIiwidGFnIjoiIn0%3D; expires=Wed, 18-May-2022 03:33:58 GMT; Max-Age=7200; path=/; httponly; samesite=lax
X-Powered-By: PHP/7.4.28
X-Powered-By: ASP.NET

响应标头(response header)是服务端发给客户端的,具体规范如下:

   Response      = Status-Line               ; Section 6.1
                   *(( general-header        ; Section 4.5
                    | response-header        ; Section 6.2
                    | entity-header ) CRLF)  ; Section 7.1
                   CRLF
                   [ message-body ]          ; Section 7.2

见下图:

file

响应的Status-Line格式:

  Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

其中Status-Code如下:

  Status-Code    =
        "100"  ; Section 10.1.1: Continue
      | "101"  ; Section 10.1.2: Switching Protocols
      | "200"  ; Section 10.2.1: OK
      | "201"  ; Section 10.2.2: Created
      | "202"  ; Section 10.2.3: Accepted
      | "203"  ; Section 10.2.4: Non-Authoritative Information
      | "204"  ; Section 10.2.5: No Content
      | "205"  ; Section 10.2.6: Reset Content
      | "206"  ; Section 10.2.7: Partial Content
      | "300"  ; Section 10.3.1: Multiple Choices
      | "301"  ; Section 10.3.2: Moved Permanently
      | "302"  ; Section 10.3.3: Found
      | "303"  ; Section 10.3.4: See Other
      | "304"  ; Section 10.3.5: Not Modified
      | "305"  ; Section 10.3.6: Use Proxy
      | "307"  ; Section 10.3.8: Temporary Redirect
      | "400"  ; Section 10.4.1: Bad Request
      | "401"  ; Section 10.4.2: Unauthorized
      | "402"  ; Section 10.4.3: Payment Required
      | "403"  ; Section 10.4.4: Forbidden
      | "404"  ; Section 10.4.5: Not Found
      | "405"  ; Section 10.4.6: Method Not Allowed
      | "406"  ; Section 10.4.7: Not Acceptable
      | "407"  ; Section 10.4.8: Proxy Authentication Required
      | "408"  ; Section 10.4.9: Request Time-out
      | "409"  ; Section 10.4.10: Conflict
      | "410"  ; Section 10.4.11: Gone
      | "411"  ; Section 10.4.12: Length Required
      | "412"  ; Section 10.4.13: Precondition Failed
      | "413"  ; Section 10.4.14: Request Entity Too Large
      | "414"  ; Section 10.4.15: Request-URI Too Large
      | "415"  ; Section 10.4.16: Unsupported Media Type
      | "416"  ; Section 10.4.17: Requested range not satisfiable
      | "417"  ; Section 10.4.18: Expectation Failed
      | "500"  ; Section 10.5.1: Internal Server Error
      | "501"  ; Section 10.5.2: Not Implemented
      | "502"  ; Section 10.5.3: Bad Gateway
      | "503"  ; Section 10.5.4: Service Unavailable
      | "504"  ; Section 10.5.5: Gateway Time-out
      | "505"  ; Section 10.5.6: HTTP Version not supported
      | extension-code

  extension-code = 3DIGIT
  Reason-Phrase  = *<TEXT, excluding CR, LF>

分类说明:

  - 1xx: Informational - Request received, continuing process

  - 2xx: Success - The action was successfully received,
    understood, and accepted

  - 3xx: Redirection - Further action must be taken in order to
    complete the request

  - 4xx: Client Error - The request contains bad syntax or cannot
    be fulfilled

  - 5xx: Server Error - The server failed to fulfill an apparently
    valid request

响应的response-header可用字段如下:

   response-header = Accept-Ranges           ; Section 14.5
                   | Age                     ; Section 14.6
                   | ETag                    ; Section 14.19
                   | Location                ; Section 14.30
                   | Proxy-Authenticate      ; Section 14.33
                   | Retry-After             ; Section 14.37
                   | Server                  ; Section 14.38
                   | Vary                    ; Section 14.44
                   | WWW-Authenticate        ; Section 14.47

在请求和响应中都有通用标头general-header和实体标头entity-header,具体可用字段如下:

   general-header = Cache-Control            ; Section 14.9
                  | Connection               ; Section 14.10
                  | Date                     ; Section 14.18
                  | Pragma                   ; Section 14.32
                  | Trailer                  ; Section 14.40
                  | Transfer-Encoding        ; Section 14.41
                  | Upgrade                  ; Section 14.42
                  | Via                      ; Section 14.45
                  | Warning                  ; Section 14.46

HTTP/1.1中设置字段Connection: close会自动关闭连接。

   entity-header  = Allow                    ; Section 14.7
                  | Content-Encoding         ; Section 14.11
                  | Content-Language         ; Section 14.12
                  | Content-Length           ; Section 14.13
                  | Content-Location         ; Section 14.14
                  | Content-MD5              ; Section 14.15
                  | Content-Range            ; Section 14.16
                  | Content-Type             ; Section 14.17
                  | Expires                  ; Section 14.21
                  | Last-Modified            ; Section 14.29
                  | extension-header

   extension-header = message-header

字段Content-Length在实体标头中是很重要的一个字段,长度为实体的字节数,值为大于等于0的十进制整数。注意在对实体主体进行编码传输时不能指定这个字段。

WEBSOCKET

HTTP协议是请求/响应协议,必须客户端发送请求,服务端才能响应,服务端不能主动给客户端发消息,这在某些情况下就很要命了,websocket协议就解决这个问题。

websocket协议是http协议的升级,必须使用GET方法,而最核心的点是请求时必须包括以下字段:

Upgrade: websocket
Connection: Upgrade

另外websocket请求的URI从http://https://变成ws://wss://,其它部分不变:

ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ]
wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ]

我们可以从这里测试websocket连接:http://mud.ren/websocket.html

以下是请求示例:

GET wss://mud.ren:8888/ HTTP/1.1
Host: mud.ren:8888
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36
Upgrade: websocket
Origin: http://mud.ren
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7,zh-TW;q=0.6
Sec-WebSocket-Key: HjWcnFsZeGhSTkEIAPGR3g==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Protocol: ascii

以下是响应示例:

HTTP/1.1 101 Switching Protocols
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Accept: 27QGbvfIaXqw2IgO8bJtOp0haH8=
Sec-WebSocket-Protocol: ascii
Sec-WebSocket-Extensions: permessage-deflate

To establish a WebSocket connection, the client sends a WebSocket handshake request, for which the server returns a WebSocket handshake response, as shown in the example below.

Client request (just like in HTTP, each line ends with \r\n and there must be an extra blank line at the end):

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com

websocket http示例:

"GET /chat HTTP/1.1\nHost: mud.ren\nUpgrade: websocket\nConnection: Upgrade\r\n\r\n";

websocket 响应示例:

HTTP/1.1 101 Switching Protocols
Date: Mon, 16 May 2022 07:20:05 GMT
Server: Ktor/debug
Upgrade: websocket
Connection: Upgrade

HTTPS

HTTPS是 HTTP over SSL,本质上是身披SSL外壳的HTTP协议,客户端和服务端通信是先建立SSL连接,然后再进行HTTP通信。

京ICP备13031296号-4