在服务器端,它实际上取决于 websockets 库的实现、语言和 API,或者您自己使用的实现。
此描述仅适用于 WebSockets 的 RAW 实现,并不基于使用任何库来处理 WebSockets 协议。库,例如 jWebSockets (Java)、SignalR、socket.io 和其他库,绝对会有另一个进程来使用 WebSockets。
如果我们谈论的是原始套接字上的原始实现,那么过程是这样的:
- 创建服务器端 TCP 套接字,绑定到特定端口并监听它,然后进入接受状态。接受可以是阻塞的或非阻塞的。我使用.Net,并进行了异步接受,这样每次连接到服务器时都会触发方法。1b。通过JS调用客户端:new WebSocket(...);
- 接受新套接字后,它必须开始接收数据。TCP 协议是基于流的,而不是基于消息的。
- WebSockets 协议要求在进行通信之前完成 WebSockets 的 HTTP 握手。因此,在接受新套接字后,您立即开始接收数据,首先您将收到握手数据 - 一些文本行。
- 继续握手过程。这意味着读取握手数据,并在服务器端生成响应握手数据并将其发送到WebSocket。4b。如果握手数据将被客户端(浏览器)验证和验证,你会得到回调“onopen”,否则你可能会得到“onerror”和“onclose”。
- 握手完成后,您可以接收和发送消息。消息是基于 WebSockets 协议的数据帧(非原始)。WebSockets 是基于 MESSAGE 的协议。因此,您必须确保在对数据进行逻辑处理之前读取特定数量的消息数据。
- 为了在服务器端接收数据,如果您使用自己的实现,则必须实现从 TCP 套接字流读取。为此,您将始终只想读取 2 个字节,如果有的话(2 个字节) - 这是标头数据,根据协议数据帧规范对其进行解码,并继续读取其余数据以找出是否有masking 然后读取掩码字节和长度。这一切都在标题中。但标题的长度可能略有不同。这就是为什么您必须先只读取 2 个字节,然后再读取一些字节的原因。获得长度后,您必须从 TCP 套接字流中准确读取此字节长度。在所有读取之后,实际数据被取消屏蔽(如果启用了屏蔽,根据我的经验,它总是启用的),之后,您可以让套接字从头开始读取一些其他数据。
- 在读取并取消屏蔽消息后,您将获得原始数据,在大多数情况下,它只是您使用“socket.send("...");”从客户端发送的字符串。
- 要发送数据,您必须获取原始字符串数据,然后使用 UTF8 编码获取字符串的字节,然后用数据帧覆盖它,因此与读取相反,唯一的区别是您不应该进行屏蔽。所以从服务器到客户端的数据不会被屏蔽。
- 在您制作二进制文件并发送后,如果一切正常,您可能会在客户端收到您发送的数据“onmessage”。
客户端永远不会收到部分数据或无序数据。它将始终按照您发送的顺序接收数据包,并且始终按照您发送的顺序接收数据包。服务器可能会部分基于低级 TCP 层进程接收数据。但会收到总是订购的。
该协议是可靠且有序的。
最流行的 WebSockets 协议RFC 6455规范,请记住 iOS 使用另一个规范,它们可能不交叉兼容,这意味着您需要专门为不同的协议实现创建另一个握手功能和数据框架。