C++ 非阻塞套接字 - 等待所有接收数据
C++ nonblocking sockets - wait for all recv data
我没有 运行 在我的本地系统上遇到这个问题(当然),但现在我正在设置一个虚拟服务器,我的部分代码遇到了一些问题。
为了从非阻塞 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()
和 运行,但由于 print/debug,我没有遇到这个问题,所以看起来程序运行很慢.
我认为这个函数对阻塞套接字非常有效,但对非阻塞套接字无效。
关于我可以采取的测量的任何建议,以确保我在非阻塞套接字上接收到所有 1024 字节而没有数据丢失?
如果你使用非阻塞模式,那么你会读取所有已经到达系统的数据。一旦你读出所有数据 recv returns 错误,原因取决于系统:
- EWOULDBLOCK(在posix系统中)
- windows 套接字系统中的 WSAEWOULDBLOCK
收到此错误后,您需要等待另一个数据的到来。您可以通过多种方式做到这一点:
- 等待 select/poll/epoll
等特殊功能
- 休眠一段时间并尝试再次接收(用户-space 轮询)
如果需要减少延迟,select/poll/epoll 更可取。睡眠更容易实现。
您还需要考虑 TCP 是流协议并且不会保持帧。这意味着您可以发送 256 个字节,然后再发送 256 个字节,但一次接收 512 个字节。这也适用于相反的方式:您可以一次发送 512 个字节,并在第一次读取时接收 256 个字节,在下一次读取时接收另外 256 个字节。
我没有 运行 在我的本地系统上遇到这个问题(当然),但现在我正在设置一个虚拟服务器,我的部分代码遇到了一些问题。
为了从非阻塞 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()
和 运行,但由于 print/debug,我没有遇到这个问题,所以看起来程序运行很慢.
我认为这个函数对阻塞套接字非常有效,但对非阻塞套接字无效。
关于我可以采取的测量的任何建议,以确保我在非阻塞套接字上接收到所有 1024 字节而没有数据丢失?
如果你使用非阻塞模式,那么你会读取所有已经到达系统的数据。一旦你读出所有数据 recv returns 错误,原因取决于系统:
- EWOULDBLOCK(在posix系统中)
- windows 套接字系统中的 WSAEWOULDBLOCK
收到此错误后,您需要等待另一个数据的到来。您可以通过多种方式做到这一点:
- 等待 select/poll/epoll 等特殊功能
- 休眠一段时间并尝试再次接收(用户-space 轮询)
如果需要减少延迟,select/poll/epoll 更可取。睡眠更容易实现。
您还需要考虑 TCP 是流协议并且不会保持帧。这意味着您可以发送 256 个字节,然后再发送 256 个字节,但一次接收 512 个字节。这也适用于相反的方式:您可以一次发送 512 个字节,并在第一次读取时接收 256 个字节,在下一次读取时接收另外 256 个字节。