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'
]
});
我正在尝试了解有关 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'
]
});