在向浏览器发送数据时构建 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 头的主要内容,如果未能解决你的问题,请参考以下文章