我当然没有在本地系统上遇到这个问题(当然),但是现在我正在设置一个虚拟服务器,我的部分代码存在一些问题。
为了从非阻塞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返回错误,原因取决于系统:
收到此错误后,您需要等待其他数据的到达。您可以通过以下几种方式实现:
如果你需要减少延迟,最好选择/ poll / epoll。睡眠实现起来要简单得多。
此外,您需要考虑TCP是流协议,并不保持框架。这意味着您可以发送例如256个字节,然后发送另外256个字节,但一次接收512个字节。这也是相反的:您可以一次发送512个字节,第一次读取时接收256个字节,下次读取时接收另外256个字节。