windows 使用 Winsock 读取所有信息时结束“recv()”循环
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3340336/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Ending "recv()" loop when all information is Read using Winsock
提问by RageD
I am having an issue in my recv() loop for winsock. I am trying to terminate the loop when iResult==0, however, the loop only ends when the socket closes. It appears to be hanging at the very last recv() where iResult would equal 0. So any ideas on how to terminate the loop effectively? My ultimate goal (whether iResult == 0 or not; perhaps I am going about this the wrong way) is to stop the loop when all the sent information has been read. Here is the loop.
我在 winsock 的 recv() 循环中遇到了问题。我试图在 iResult==0 时终止循环,但是,循环仅在套接字关闭时结束。它似乎挂在 iResult 等于 0 的最后一个 recv() 处。那么有关如何有效终止循环的任何想法?我的最终目标(无论 iResult == 0 与否;也许我的做法是错误的)是在读取所有发送的信息后停止循环。这是循环。
do
{
iResult = recv(socket, recvbuf, BUFLEN-1, 0);
if(iResult > 0){
// Null byte :)
// Remove that garbage >:(
recvbuf[iResult] = 'u_long iMode = 1;
ioctlsocket(socket, FIONBIO, &iMode);
';
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);
Like I said, I am receiving all the data, I just cannot exit the loop. The next step would to be write data back to the server, but it hangs here until ping timeout. Socket is SOCK_STREAM and BUFLEN is defined as 0x200
就像我说的,我正在接收所有数据,但我无法退出循环。下一步是将数据写回服务器,但它会挂在这里直到 ping 超时。套接字为 SOCK_STREAM,BUFLEN 定义为 0x200
Thanks
谢谢
采纳答案by Dan Breslau
By default, instead of returning 0, recv
blocks if there's no data to receive:
默认情况下,recv
如果没有要接收的数据,则阻塞而不是返回 0 :
If no incoming data is available at the socket, the recv call blocks and waits for data to arrive according to the blocking rules defined for WSARecv with the MSG_PARTIAL flag not set unless the socket is nonblocking. In this case, a value of SOCKET_ERROR is returned with the error code set to WSAEWOULDBLOCK. The select, WSAAsyncSelect, or WSAEventSelect functions can be used to determine when more data arrives.
如果套接字上没有可用的传入数据,则 recv 调用将根据为 WSARecv 定义的阻塞规则阻塞并等待数据到达,除非套接字是非阻塞的,否则未设置 MSG_PARTIAL 标志。在这种情况下,将返回 SOCKET_ERROR 值,并将错误代码设置为 WSAEWOULDBLOCK。select、WSAAsyncSelect 或 WSAEventSelect 函数可用于确定何时有更多数据到达。
You can use ioctlsocketto put the socket in non-blocking mode:
您可以使用ioctlsocket将套接字置于非阻塞模式:
##代码##EDIT: Here's the setsockopt suggestion that I made in an earlier rev, then removed (see comments):
编辑:这是我在较早的版本中提出的 setsockopt 建议,然后删除(见评论):
You can use the setsockoptfunction with the
SO_RCVTIMEO
option to set the socket to timeout onrecv
if no data is available.
如果没有数据可用,您可以使用 带有选项的setsockopt函数
SO_RCVTIMEO
将套接字设置为超时recv
。
回答by seand
When you design a TCP communication mechanism you have to define message boundaries. (often \r\n). In of itself, tcp doesn't know about boundaries; you have to do this yourself. The recv() call may not always return on a message boundary. One send() might get split into multiple recv()-s on the other end.
当您设计 TCP 通信机制时,您必须定义消息边界。(通常\r\n)。就其本身而言,tcp 不知道边界;你必须自己做这件事。recv() 调用可能并不总是在消息边界上返回。一个 send() 可能会在另一端拆分为多个 recv()-s。