gpt4 book ai didi

C++ 非阻塞套接字 - 等待所有接收数据

转载 作者:搜寻专家 更新时间:2023-10-31 00:27:44 25 4
gpt4 key购买 nike

我在我的本地系统上并没有遇到这个问题(当然),但是现在我正在设置一个虚拟服务器,我的部分代码遇到了一些问题。

为了从非阻塞 TCP recv() 接收所有数据,我有这个函数

ssize_t Server::recvAll(int sockfd, const void *buf, size_t len, int flags) {
// just showing here that they are non-blocking sockets
u_long iMode=1;
ioctlsocket(sockfd,FIONBIO,&iMode);

ssize_t result;
char *pbuf = (char *)buf;
while ( len > 0 ) {
result = recv(sockfd,pbuf,len,flags);
printf("\tRES: %d", result);
if ( result <= 0 ) break;
pbuf += result;
len -= result;
}

return result;
}

我注意到 recvAll 通常 打印 RES: 1024(1024 是我发送的字节数)并且效果很好.但不太常见的是,数据丢失并且它仅打印 RES: 400(其中 400 是大于 0 且小于 1024 的某个数字)并且我的代码不起作用,因为它需要所有 1024 个字节。

我也试过打印 WSAGetLastError() 并在调试中运行,但由于打印/调试,我没有遇到这个问题,看起来程序运行得足够慢。

我认为这个函数对阻塞套接字非常有效,但对非阻塞套接字无效。

关于我可以采取的测量的任何建议,以确保我在非阻塞套接字上确实接收到所有 1024 字节而没有数据丢失?

最佳答案

如果你使用非阻塞模式,那么你会读取所有已经到达系统的数据。读出所有数据后,recv 返回错误,原因取决于系统:

  • EWOULDBLOCK(在 posix 系统中)
  • Windows 套接字系统中的 WSAEWOULDBLOCK

一旦收到此错误,您需要等待另一个数据的到来。您可以通过多种方式做到这一点:

  • 等待 select/poll/epoll 等特殊函数
  • 休眠一段时间并尝试再次接收(用户空间轮询)

如果需要减少延迟,最好选择/poll/epoll。 sleep 实现起来要简单得多。

您还需要考虑 TCP 是流协议(protocol)并且不会保持帧。这意味着您可以发送 256 个字节,然后再发送 256 个字节,但一次接收 512 个字节。这也适用于相反的方式:您可以一次发送 512 个字节,并在第一次读取时接收 256 个字节,在下一次读取时接收另外 256 个字节。

关于C++ 非阻塞套接字 - 等待所有接收数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47975612/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com