SocketIO websocket 握手与 RFC 6455 描述的不同

SocketIO websocket handshake is different from what is described by RFC 6455

我正在尝试了解有关 websockets 协议的更多信息。根据 RFC 6455,此协议的步骤是握手,从 HTTP 升级请求开始:

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

服务器用 HTTP 切换协议消息响应:

HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
    Sec-WebSocket-Protocol: chat

我尝试使用一个基于 socketIO(nodeJS websockets 库)的简单程序来观察这一点。捕获流量后,我注意到客户端发送给服务器的第一条消息是:

GET /socket.io/?EIO=3&transport=polling&t=1443149751115-0 HTTP/1.1
Host: localhost
Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36            (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36
Origin: null
Accept: */*
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8

服务器响应:

HTTP/1.1 200 OK
Content-Type: application/octet-stream
Content-Length: 101
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: null
Set-Cookie: io=3Z_TCqv9LKKXcWCjAAAD
Date: Fri, 25 Sep 2015 02:55:51 GMT
Connection: keep-alive

....0{"sid":"3Z_TCqv9LKKXcWCjAAAD","upgrades":    ["websocket"],"pingInterval":25000,"pingTimeout":60000}

SocketIO 是否没有遵循 websockets 的 RFC 还是我遗漏了什么?

socket.io 在连接到 webSocket 之前有自己的连接管理功能,允许它协商实际要与服务器建立的连接类型,并允许它向服务器发送一些配置选项客户。如果您正在尝试研究普通的 webSocket,这会让您感到困惑。

socket.io 是 webSocket 之上的附加协议。它最终会在底层使用一个标准的 webSocket,但它会有一些额外的东西。如果您继续关注 socket.io 连接,您最终会看到一个标准的 webSocket 连接。

我建议您首先从您的客户端建立一个普通的 webSocket 连接(没有 socket.io)并研究该网络跟踪。

我相信你是对的,socket.io 不遵守 RFC 6455。为了对此进行测试,我 运行 在 ubuntu virtualbox 中安装了 javascript 服务器,并在主机 ubuntu 与服务器进行了成功的 socket.io 交互。我使用 sudo tcpdump -i vboxnet1 -w dump.out 捕获网络流量并使用 wireshark 分析结果。

socket.io 握手就像原始发帖人所描述的那样,整个脚本成功完成(客户端接收到 websocket 消息),tcpdump 从未显示带有升级的 HTTP 请求 header 根据 https://www.rfc-editor.org/rfc/rfc6455#section-4.1

在 js 客户端,使用 websocket 传输连接到服务器。这启用了与 RFC 6455 相同的默认 websocket 机制。

var socket = io.connect('http://localhost:8080', {
   transports: [
     'websocket',
     'polling'
   ]
});