在服务器端,它实际上取决于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个字节,然后再读取2个字节。获得长度后,必须从TCP套接字流中准确读取此长度的字节。在所有读取之后,实际数据被解除屏蔽(如果启用了屏蔽,根据我的经验始终启用),然后,您可以将套接字从一开始读取其他数据。在完成当前阅读之前,不要开始阅读新消息。
- 消息被读取和解密后,您将获得原始数据,在大多数情况下,它只是您使用“socket.send(”...“);”从客户端发送的字符串。
- 要发送数据,您必须采取原始字符串数据,然后使用UTF8编码获取字符串的字节,并在数据成帧之后进行覆盖,因此与读数相反,唯一的区别是您不应该执行屏蔽。所以从服务器到客户端的数据不会被屏蔽。
- 在您制作二进制文件并发送之后,如果一切正常,您可能会在客户端收到您发送的数据的“onmessage”。
客户端永远不会收到部分数据或无序数据。它会一直收到您发送的数据包,并始终按照您发送的数据包发送。 服务器可能部分基于低层TCP层进程接收数据。但会收到总是有序的。
该协议是可靠和有序的。
最流行的WebSockets协议规范RFC 6455,请记住,iOS使用另一个规范,它们可能不是交叉兼容的,这意味着您需要为不同的协议实现专门创建另一个握手功能和数据成帧。
优秀的答案。我正尝试从Java服务器中的[binaryjs](http://binaryjs.com/)读取一串字节。考虑到没有binaryjs Java服务器,这是否可以采用这种方法? – eskalera
是的。上面的文本描述了适用于任何WebSocket应用程序的WebSocket传输协议,而binaryjs使用WS作为传输协议。 但是你必须在它之上实现遵循binaryjs规范的数据协议。 – moka