Webscoket是Web瀏覽器和服務器之間的一種全雙工通信協議。一旦Web客戶端與服務器建立起連接,之后的全部數據通信都通過這個連接進行。通信過程中,可互相發送JSON、XML、HTML或圖片等任意格式的數據。
WS(WebSocket)與HTTP協議比較:
都是基於TCP的應用層協議; 都使用Request/Response模型進行連接的建立; 在連接的建立過程中對錯誤的處理方式相同,在這個階段WS可能返回和HTTP相同的返回碼; 都可以在網絡中傳輸數據。
不同之處
WS使用HTTP來建立連接,但是定義了一系列新的header域,這些域在HTTP中並不會使用;
WS的連接不能通過中間人來轉發,它必須是一個直接連接;
WS連接建立之后,通信雙方都可以在任何時刻向另一方發送數據;
WS連接建立之后,數據的傳輸使用幀來傳遞,不再需要Request消息;
WS的數據幀有序。
WS整個通信過程如下圖所示:
websocket是基於TCP的一個應用協議,與HTTP協議的關聯之處在於websocket的握手數據被HTTP服務器當作HTTP包來處理,主要通過Update request HTTP包建立起連接,之后的通信全部使用websocket自己的協議。
**請求:**TCP連接建立后,客戶端發送websocket的握手請求,請求報文頭部如下:
GET /uin=xxxxxxxx&app=xxxxxxxxx&token=XXXXXXXXXXXX HTTP/1.1 Host: server.example.cn:443 Connection: Upgrade Pragma: no-cache Cache-Control: no-cache User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Upgrade: websocket Sec-WebSocket-Version: 13 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: user_id=XXXXX Sec-WebSocket-Key: 1/2hTi/+eNURiekpNI4k5Q== Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits Sec-WebSocket-Protocol: binary, base64
第一行為為請求的方法,類型必須為GET,協議版本號必須大於1.1
Upgrade字段必須包含,值為websocket
Connection字段必須包含,值為Upgrade
Sec-WebSocket-Key字段必須包含 ,記錄着握手過程中必不可少的鍵值。
Sec-WebSocket-Protocol字段必須包含 ,記錄着使用的子協議
Origin(請求頭):Origin用來指明請求的來源,Origin頭部主要用於保護Websocket服務器免受非授權的跨域腳本調用Websocket API的請求。也就是不想沒被授權的跨域訪問與服務器建立連接,服務器可以通過這個字段來判斷來源的域並有選擇的拒絕。
**響應:**服務器接收到請求后,返回狀態碼為101 Switching Protocols 的響應。
HTTP/1.1 101 Switching Protocols Server: WebSockify Python/2.6.6 Date: Wed, 27 May 2020 03:03:21 GMT Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: hXXXXXXXXXXXXXXxGmM= Sec-WebSocket-Protocol: binary
Sec-WebSocket-Accept字段是由握手請求中的Sec-WebSocket-Key字段生層的。
握手成功后,通信不再使用HTTP協議,而采用WebSocket獨立的數據幀。如下圖所示,為協議幀格式:
FIN,指明Frame是否是一個Message里最后Frame(之前說過一個Message可能又多個Frame組成);1bit,是否為信息的最后一幀 RSV1-3,默認是0 (必須是0),除非有擴展定義了非零值的意義。 Opcode,這個比較重要,有如下取值是被協議定義的 0x00 denotes a continuation frame 0x01 表示一個text frame 0x02 表示一個binary frame 0x03 ~~ 0x07 are reserved for further non-control frames,為將來的非控制消息片段保留測操作碼 0x08 表示連接關閉 0x09 表示 ping (心跳檢測相關) 0x0a 表示 pong (心跳檢測相關) 0x0b ~~ 0x0f are reserved for further control frames,為將來的控制消息片段保留的操作碼 Mask,這個是指明“payload data”是否被計算掩碼。這個和后面的Masking-key有關,如果設置為1,掩碼鍵必須放在masking-key區域,客戶端發送給服務端的所有消息,此位的值都是1; Payload len,數據的長度, Masking-key,0或者4bit,只有當MASK設置為1時才有效。,給一個Websocket中掩碼的意義 Payload data,幀真正要發送的數據,可以是任意長度,但盡管理論上幀的大小沒有限制,但發送的數據不能太大,否則會導致無法高效利用網絡帶寬,正如上面所說Websocket提供分片。 Extension data:擴展數據,如果客戶端和服務端沒有特殊的約定,那么擴展數據長度始終為0 Application data:應用數據,