我在winsock的recv()循环中遇到了问题。我试图在iResult == 0时终止循环,但是,循环仅在套接字关闭时结束。它似乎挂在最后一个recv(),其中iResult等于0.那么有关如何有效终止循环的任何想法?我的最终目标(无论iResult是否= 0;或许我的方法是错误的)是在读取所有发送的信息时停止循环。这是循环。
do
{
iResult = recv(socket, recvbuf, BUFLEN-1, 0);
if(iResult > 0){
// Null byte :)
// Remove that garbage >:(
recvbuf[iResult] = '\0';
printf("Recvbuf: %s\n\n\niResult: %d\n",recvbuf,iResult);
continue; // working properly
}
else if(iResult == 0)
// Connection closed properly
break;
else
{
printf("ERROR! %ld",WSAGetLastError());
break;
}
} while(iResult > 0);
像我说的那样,我收到的所有数据,我都无法退出循环。下一步是将数据写回服务器,但它会挂起,直到ping超时。套接字是SOCK_STREAM,BUFLEN定义为0x200
由于
答案 0 :(得分:4)
默认情况下,recv
blocks if there's no data to receive:
如果没有可用的传入数据 套接字,recv调用块和 根据数据等待数据到达 为WSARecv定义的阻止规则 未设置MSG_PARTIAL标志 除非套接字是非阻塞的。在 在这种情况下,SOCKET_ERROR的值是 返回错误代码设置为 WSAEWOULDBLOCK。选择, WSAAsyncSelect或WSAEventSelect 函数可用于确定 当更多数据到达时。
您可以使用ioctlsocket将套接字置于非阻塞模式:
u_long iMode = 1;
ioctlsocket(socket, FIONBIO, &iMode);
编辑:这是我在之前版本中制作的setsockopt建议,然后删除(请参阅评论):
您可以使用setsockopt 使用
SO_RCVTIMEO
选项运行 在recv
上将套接字设置为超时 如果没有数据可用。
答案 1 :(得分:1)
设计TCP通信机制时,必须定义消息边界。 (经常\ r \ n)。就其本身而言,tcp不了解边界;你必须自己做。 recv()调用可能并不总是在消息边界上返回。一个send()可能会在另一端拆分为多个recv() - 。