了解服务器端的WebSockets技术

8
我对websocket通信有一些疑问。据我了解,在客户端,它的工作方式如下:
  1. 从客户端,使用"new WebSocket('ws://blahblah')"创建一个新的Socket处理程序
  2. 然后使用onOpen()方法确定我们已连接到WS服务器
  3. 使用onMessage()方法,确定已从WS服务器接收到消息
  4. OnClose()方法指示套接字连接已关闭
从客户端的角度来看很清楚。但从服务器的角度来看,流程是怎样的(就像上面的客户端那样),什么是websocket服务器进程,当我们说通信在TCP上发生时,确切地是什么意思,我们如何检查这一点(如果问题太基础,我的歉意)。
请有人解释一下。谢谢。
2个回答

9

在服务器端,这实际上取决于您使用的Websockets库或您自己的实现方式、语言和API。

此描述仅适用于WebSockets的RAW实现,不基于使用任何库来处理WebSockets协议。 像jWebSockets(Java)、SignalR、socket.io等库将有完全不同的处理WebSockets过程。

如果我们谈论原始套接字的原始实现,那么流程如下:

  1. 创建服务器端TCP套接字,绑定到特定的端口并监听它,然后进入接受状态。接受可以是阻塞或非阻塞的。我使用的是.Net,并进行了异步接受,这样每次有连接到服务器时都会触发方法。 1b. 通过JS调用客户端:new WebSocket(...);
  2. 在接受新套接字之后,必须开始接收数据。TCP协议是基于流而不是消息的。
  3. WebSockets协议要求在通信之前完成WebSockets的HTTP握手。因此,在接受新套接字之后立即开始接收数据,首先接收到的是握手数据 - 一些文本行。
  4. 进行握手过程。这意味着读取握手数据,并在服务器端生成响应握手数据并将其发送到WebSocket。 4b. 如果客户端(浏览器)验证和验证了握手数据,则会获得回调“onopen”,否则您可能会获得“onerror”和“onclose”。
  5. 握手完成后,您可以接收和发送消息。根据WebSockets协议,消息是基于数据框架(而不是原始数据)的。而且WebSockets是基于消息的协议。因此,您必须确保在处理逻辑数据之前读取特定数量的消息数据。
  6. 对于在服务器端接收数据,如果使用自己的实现,则必须从TCP套接字流中实现读取。为此,您将始终只想要读取2个字节,如果有一些(2个字节)-这是标题数据,请根据协议数据框架规范进行解码,并继续读取其余数据以找出是否有屏蔽然后读取屏蔽字节和长度。这都在标题中。但是标题可能长度略有不同。这就是为什么您首先只需读取2个字节,然后再读取一些字节。在获取长度之后,您必须从TCP套接字流中准确地读取这个长度的字节。在所有读取完成并且实际数据被解除屏蔽(如果启用了屏蔽,则从我的经验来看,它始终是启用的)之后,您可以将套接字放在从头开始读取其他数据的状态。在完成当前消息的阅读之前,请勿开始阅读新消息。
  7. 在消息被读取和解除屏蔽之后,您将获得原始数据,在大多数情况下,它只是通过“socket.send(“…”)”从客户端发送的字符串。
  8. 要发送数据,您必须获取原始字符串数据,然后使用UTF8编码获取字符串的字节,并在其上覆盖数据框架,因此与读取相反,唯一的区别是您不应该进行屏蔽。因此,从服务器到客户端的数据未经过屏蔽。
  9. 在制作二进制文件并发送它之后,如果一切正常,您可能会在客户端收到“onmessage”和您发送的数据。

客户端永远不会接收到部分数据或无序数据。它将始终按照您发送的顺序接收数据包,并始终按照您发送的方式接收。

此协议是可靠和有序的。

WebSockets协议最流行的规范是RFC 6455,请注意iOS使用另一种规范,它们可能不兼容,这意味着您需要为不同的协议实现创建另一个握手功能和数据框架。


1
非常好的回答。我正在尝试从Java服务器中读取来自binaryjs的字节流。考虑到没有二进制的Java服务器,是否可以按照这种方法实现? - eskalera
是的。上面的文本描述了适用于任何WebSocket应用程序的WebSocket传输协议,而binaryjs使用WS作为传输协议。 但是您将需要在其之上实现遵循binaryjs规范的数据协议。 - moka

0
握手完成后,您可以接收和发送消息。基于WebSockets协议,消息是数据帧(而不是原始数据)。而WebSockets是基于消息的协议。因此,在处理逻辑数据之前,您必须确保读取特定数量的消息数据。
以下是更多信息:
- Netty - Framing: Netty - Framing - http://www.ietf.org/mail-archive/web/hybi/current/msg07641.html: http://www.ietf.org/mail-archive/web/hybi/current/msg07641.html - http://www.lenholgate.com/blog/2011/07/websockets-is-a-stream-not-a-message-based-protocol.html: http://www.lenholgate.com/blog/2011/07/websockets-is-a-stream-not-a-message-based-protocol.html 因此,服务器可以将消息分段为多个WebSocket帧,并将其发送到客户端。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接