一次websocket的抓包體驗

一個簡單的demo

咱們知道websocket一種服務端推送技術,首先Websocket是基於HTTP協議的,或者說借用了HTTP的協議來完成一部分握手。後續數據傳遞是基於TCP的。javascript

客戶端代碼

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>websocket client</title>
</head>
<body>
  <button id="open">open</button>
  <button id="send">send</button>
  <button id="close">close</button>
  <script type="text/javascript">
    (function (){
      let ws = null;

      document.querySelector("#open").addEventListener('click', e => {
        ws = new WebSocket("ws://127.0.0.1:8080");

        ws.addEventListener('open', e => console.log('open event, %o', e));
        ws.addEventListener('message', e => console.log('message event, %o', e));
        ws.addEventListener('close', e => console.log('close event, %o', e));
        ws.addEventListener('error', e => console.log('error event, %o', e));
      });

      document.querySelector("#send").addEventListener('click', e => {
        ws.send('hello');
      });

      document.querySelector("#close").addEventListener('click', e => {
        ws.close();
        ws = null;
      });
    })()
  </script>
</body>
</html>

服務端代碼

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', function connection(ws) {
  ws.on('message', function incoming(message) {
    console.log('received: %s', message);
    ws.send('hello too!');
  });

  ws.send('something');
});

輸出結果

open event, Event
message event, MessageEvent
message event, MessageEvent
close event, CloseEvent

細節

求頭信息

從瀏覽器中能夠看到ws握手的請求頭信息html

GET ws://127.0.0.1:8080/ HTTP/1.1
Host: 127.0.0.1:8080
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: http://zj.h5.m.taobao.com
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.8
Cookie: OUTFOX_SEARCH_USER_ID_NCOO=1973383732.1783078; l=AujoRgw9fUEEs1APUgk9dNwgONz6EUwb
Sec-WebSocket-Key: 7iAt/aVzQLvkwZmO6eHr3A==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

解釋:java

Upgrade: websocket
Connection: Upgrade

表示發起的是Websocket協議。web

返回頭信息

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 32BWzg94jPj8C0kXzqHAru5pGbw=

101 code 轉換協議:101 Switching Protocols
服務器已經理解了客戶端的請求,並將經過Upgrade 消息頭通知客戶端採用不一樣的協議來完成這個請求。在發送完這個響應最後的空行後,服務器將會切換到在Upgrade 消息頭中定義的那些協議。
只有在切換新的協議更有好處的時候才應該採起相似措施。例如,切換到新的HTTP 版本比舊版本更有優點,或者切換到一個實時且同步的協議以傳送利用此類特性的資源。shell

之上是應用層協議的內容,用wireshark抓包看下底層細節,先梳理下TCP協議自己。瀏覽器

wireshark

websocket握手

這是握手時HTTP協議底層依賴的TCP三次握手機制:最後一個是告訴客戶端沒有內容發送了。8080 爲服務端端口號,61476 端口爲客戶端端口號。服務器

websocket 握手成功

HTTP 101 協議轉換

從HTTP 協議轉爲 websocket 協議,5001 端口號爲 websocket 服務的端口號。websocket

websocket 的一個數據包

關閉 websocket

能夠看出61475端口一開始爲HTTP服務的,後來因爲101返回碼,61475 端口轉爲 websocket 的 5001 端口號,服務端的8080端口對接客戶端的5001端口號。關閉websocket時,由 61475 端口號發起關閉 5001 請求,與此同時 61475 端口和 服務端的8080端口通訊,告訴服務端我要關閉端口,成功後61475 再告訴 5001 端口,我關閉成功了。整個關閉流程結束。socket

相關文章
相關標籤/搜索