webSockets 和常规套接字不是一回事。 webSocket 在常规套接字上运行,但在常规套接字之上运行自己的连接方案、安全方案和帧协议,并且两个端点都必须遵循这些附加步骤才能建立连接。您可以在这里查看 webSocket 协议:https://www.rfc-editor.org/rfc/rfc6455
最大的不同是所有的 webSocket 连接都是从客户端到服务器的 HTTP 请求开始的。客户端向完全相同的服务器和为正常 Web 通信打开的端口发送 HTTP 请求(默认为端口 80,但如果 Web 服务器在不同的端口上运行,则 webSocket 通信将在另一个端口上跟随它) .客户端设置了一些自定义标头,其中最重要的是指示客户端希望“升级”到 webSocket 协议的标头。此外,双方交换一些安全密钥。如果服务器同意“升级”,则客户端和服务器都将通过原始套接字使用的协议从 HTTP 切换到 webSocket,现在使用 webSocket 框架协议。
此外,初始 HTTP 请求中可以有一个请求路径,以指示 webSocket 请求的“子目标”。这允许使用相同的服务器和端口发起各种不同的 webSocket 请求。
还有一个带有Sec-WebSocket-Protocol 标头的可选子协议说明符,它允许请求进一步识别子协议(常见的可能是“聊天”),以便双方可以就一组特定的消息标识符和它们可能被使用的对应含义。
webSocket 连接以 HTTP 连接开始这一事实至关重要,因为如果您可以访问 Web 服务器以进行正常的 Web 通信,那么您可以通过 WebSocket 请求访问它,而无需客户端和服务器之间的任何网络基础设施。在防火墙中打开新漏洞或打开新端口或类似的东西。
您可以在此处查看如何启动 webSocket 连接的精彩摘要:https://developer.mozilla.org/en-US/docs/WebSockets/Writing_WebSocket_servers。
webSocket 协议还定义了 ping 和 pong 数据包,帮助双方了解空闲的 webSocket 是否仍然连接。
人们只能假设将 webSockets 引入所有常见浏览器需要一段时间的原因与许多有用的功能需要一段时间的原因相同。首先,一群积极进取的人必须确定并就需求达成一致,然后该小组需要带头制定解决问题的方法,然后这个想法会得到一段时间的支持,要么收集支持并处理反对意见,要么与他们竞争解决此类问题的替代方法,然后它似乎有足够的动力实际上可以成为标准,然后有人决定在浏览器和匹配的服务器实现中进行测试/试验实现(有时这一步来得更早)。然后,如果它仍在寻找动力并且似乎在标准轨道上,其他浏览器制造商将接受这个想法并开始实施。一旦所有浏览器制造商都有一个体面的工作实现(通常会有几轮标准改进,因为不同的实现会发现规范中的漏洞,或者早期开发人员发现问题或缺少功能或安全问题)。然后,至少有两个主要浏览器在其最新版本中具有该功能,该标准被认为相对可靠,消费者开始采用这些浏览器,并且一些网站开始通过使用新功能来改善他们的用户体验。那时,尾随浏览器开始感到实施它的压力。然后,有时几年后,所有主要浏览器都具有该功能,并且这些浏览器具有足够的整体用户采用率,以至于网站可以依赖该功能(无需在浏览器不支持该功能时使用主要的第二个后备设计) .整个过程可能需要很多很多年。
下面是初始化 webSocket 连接的初始 HTTP 请求示例:
GET /chat HTTP/1.1
Host: example.com:8000
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
而且,服务器响应:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
还有一个数据框示例:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+