因为LPC提供了socket功能,通过socket可以实现各种标准协议通信,这里整理一下HTTP和WEBSOCKET协议相关内容,方便需要的同学。
超文本传输协议(Hypertext Transfer Protocol -- HTTP/1.1):
WebSocket协议(The WebSocket Protocol):
HTTP Header Field Registrations:
HTTP/2.0中文翻译:
HTTP
简单的说,HTTP协议就是WWW网站用到的协议,这是一个请求/响应协议:用户从客户端(浏览器)向服务器发送请求(输入网址),服务器收到请求后响应内容。
Http URL
正常用户是通过URL使用客户端(浏览器)向服务端发送请求,HTTP URL规范如下:
http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]
请求和响应是有规范格式的,这一切都由客户端和服务端转换处理了,用谷歌浏览器按F12打开开发者模式,访问 http://mud.ren
在网络控制台可以看到请求和响应的细节:
请求标头
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
可见下图:
请求的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.1
和HTTP/1.0
最核心的区别有二点:
- HTTP/1.1默认是长连接(
Connection: Keep-Alive
) - 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
见下图:
响应的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通信。