在向浏览器发送数据时构建 websocket 头

Posted

技术标签:

【中文标题】在向浏览器发送数据时构建 websocket 头【英文标题】:building websocket head, when sending data to browser 【发布时间】:2014-03-08 23:44:32 【问题描述】:

我有一个简单的 iocp 服务器,它需要通过 websocket 向浏览器发送 1024(或更多)字节。 根据这个关于 websocket 的 RFC:

  +-+-+-+-+-------+-+-------------+-------------------------------+
    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 ...                |
   +---------------------------------------------------------------+

我以这种方式构建 websocket 头:

   char BufferToSend[1028]; //+4 bytes for websocket head

   BufferToSend[0]=130; // 10000010
   BufferToSend[1]=126; // 01111110 first bit 0 means unmask message
   BufferToSend[2] = //  2 bytes for payload size
   BufferToSend[3] = //
   BufferToSend[4] = // payload starts
   .....
   // sending data to browser
   WSASend(Socket, &wsabuf,1,&dwSendNumBytes..); //wsabuf refers to BufferToSend

第一个字节 (10000010) 由设置为 1 的第一位“fin”、三个保留位和二进制帧的操作码“0010”组成。我总是将“fin”位设置为 1,这意味着它是最后一帧,因为我假设 WSAsend 一次性将缓冲区发送到浏览器。但是,如果 WSAsend 需要调用不止一次来发送所有缓冲区怎么办?如果要发生两个 Wsasend 调用,在第一次调用中我应该将 fin 设置为 0(消息的一部分),然后在第二次调用中设置为 1(最后一帧)吗?此外,我在调用 WSasend 之前构建了 websocket 头(我不知道一次或多次),我怎么知道何时将 fin 位设置为 1 或 0?

提前感谢您的帮助。

【问题讨论】:

【参考方案1】:

FIN 位与 TCP 帧无关。它只是表明该帧是最后一个 Web 套接字帧。实际上,有效载荷有可能在两个或更多 TCP 帧中发送,但这对 Web 套接字协议没有影响。 Web 套接字实现往往具有最大 Web 套接字帧大小(不能从握手中得出)。每当帧太大时,您将收到一个错误代码,指示数据过多。但在大多数情况下,网络套接字实现可以处理任何网络套接字帧大小(当然取决于可用内存)。

【讨论】:

感谢帮助。当我需要为有效载荷调用第二个 WSAsend 时,我是否需要为第二次调用再次构建 websocket 头,或者我应该只发送没有 websocket 头的其余有效载荷并为设置 fin 位而烦恼? 您需要为使用 Web 套接字发送的所有内容创建一个标头。除了最后一帧之外的所有帧都应将 FIN 位设置为零。

以上是关于在向浏览器发送数据时构建 websocket 头的主要内容,如果未能解决你的问题,请参考以下文章

axios.get() 在向后端发送请求时正在组合 url。

教你用IDEA构建WebSocket工程...

浏览器websocket

如何在浏览器中显示大量 websocket 消息?

C++ 中的 Websocket 服务器发送消息时出错

websocket在webRTC中的作用是啥?