如何在 C 编程的 BSD 套接字中从 recv() 接收数据块?
How to receive CHUNK's of data from recv() in BSD Sockets in C programming?
我已经使用套接字在 C 中实现了一个 websocket 客户端库。它与许多 websocket 服务器一起正常工作。但是当我尝试连接我的一个客户服务器时,websocket 消息来自许多数据块。对于所有其他服务器,当我使用 recv() 时,它将完全接收一个完整的 websocket 帧,但是这个特定的服务器将在 2 个 TCP 数据包中发送一个 websocket 帧,所以我必须再次使用 recv() 来获取剩余的 websocket 帧。然后我尝试用一些 websocket 客户端工具检查这个服务器,它工作正常。我需要知道逻辑,为此实现 recv() 以及如何连接和计算何时完全接收到 websocket 帧以解析数据?请有人帮助我。
while(1){
ws_recv_ret = recv(*ws_sock, ws_recv, 1024, 0);
ws_parser_execute(&ws_frame_parser1, ws_recv);
}
TCP recv 允许接收任意数量 的字节数,直到您要求的最大数量。 “数据包”完全无法预测,您绝对不能依赖它们。
如何判断 websocket 框架的大小?当然,您使用的是 websocket 协议。 websocket header 告诉您 websocket 帧中有多少字节。您需要继续调用 recv 直到您拥有所有字节。
如果您接收到太多字节,那么您需要保存多余的字节并将它们用于下一帧。如果你仔细计算一次要接收多少字节,那么你永远不会接收太多,但许多程序确实会尝试接收尽可能多的字节,因为这样效率更高,因此它们需要处理额外的字节。
当然,因为“数据包”完全不可预测,“数据包”可能会在 header 的中间结束。所以你需要一直调用recv直到你有整个header,然后你就知道有多少字节了,然后你需要一直调用recv直到你有所有的字节。
更烦人的是,websocket headers 可以有不同的大小。所以你需要一直调用recv直到你知道header有多大,然后你需要一直调用recv直到你拥有整个header,然后你需要继续调用recv直到你拥有所有字节。
我在 recv 中使用了 MSG_DONTWAIT 标志,在循环中使用了 运行 并将新数据附加到缓冲区。之后 recv 抛出 -1 和 errno EAGAIN 然后我打破循环并解析 websocket 数据。并感谢@user253751 的解释,它有助于消除我心中对实现的一些疑虑。下面是我在我的库中使用的代码片段。
ws_recv_totalSize = 0;
ws_recv_ret = 0;
while(1){
ws_recv_totalSize += ws_recv_ret;
ws_recv_ret = recv(*ws_sock, ws_recv + ws_recv_totalSize, MAX_BUFFER- ws_recv_totalSize, MSG_DONTWAIT);
if(ws_recv_ret <= 0)
break;
}
我已经使用套接字在 C 中实现了一个 websocket 客户端库。它与许多 websocket 服务器一起正常工作。但是当我尝试连接我的一个客户服务器时,websocket 消息来自许多数据块。对于所有其他服务器,当我使用 recv() 时,它将完全接收一个完整的 websocket 帧,但是这个特定的服务器将在 2 个 TCP 数据包中发送一个 websocket 帧,所以我必须再次使用 recv() 来获取剩余的 websocket 帧。然后我尝试用一些 websocket 客户端工具检查这个服务器,它工作正常。我需要知道逻辑,为此实现 recv() 以及如何连接和计算何时完全接收到 websocket 帧以解析数据?请有人帮助我。
while(1){
ws_recv_ret = recv(*ws_sock, ws_recv, 1024, 0);
ws_parser_execute(&ws_frame_parser1, ws_recv);
}
TCP recv 允许接收任意数量 的字节数,直到您要求的最大数量。 “数据包”完全无法预测,您绝对不能依赖它们。
如何判断 websocket 框架的大小?当然,您使用的是 websocket 协议。 websocket header 告诉您 websocket 帧中有多少字节。您需要继续调用 recv 直到您拥有所有字节。
如果您接收到太多字节,那么您需要保存多余的字节并将它们用于下一帧。如果你仔细计算一次要接收多少字节,那么你永远不会接收太多,但许多程序确实会尝试接收尽可能多的字节,因为这样效率更高,因此它们需要处理额外的字节。
当然,因为“数据包”完全不可预测,“数据包”可能会在 header 的中间结束。所以你需要一直调用recv直到你有整个header,然后你就知道有多少字节了,然后你需要一直调用recv直到你有所有的字节。
更烦人的是,websocket headers 可以有不同的大小。所以你需要一直调用recv直到你知道header有多大,然后你需要一直调用recv直到你拥有整个header,然后你需要继续调用recv直到你拥有所有字节。
我在 recv 中使用了 MSG_DONTWAIT 标志,在循环中使用了 运行 并将新数据附加到缓冲区。之后 recv 抛出 -1 和 errno EAGAIN 然后我打破循环并解析 websocket 数据。并感谢@user253751 的解释,它有助于消除我心中对实现的一些疑虑。下面是我在我的库中使用的代码片段。
ws_recv_totalSize = 0;
ws_recv_ret = 0;
while(1){
ws_recv_totalSize += ws_recv_ret;
ws_recv_ret = recv(*ws_sock, ws_recv + ws_recv_totalSize, MAX_BUFFER- ws_recv_totalSize, MSG_DONTWAIT);
if(ws_recv_ret <= 0)
break;
}