【发布时间】:2015-04-08 17:04:46
【问题描述】:
尝试编写一个客户端,它将尝试接收数据直到 3 秒。我已经通过下面的代码使用 select 实现了连接方法。
//socket creation
m_hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
m_stAddress.sin_family = AF_INET;
m_stAddress.sin_addr.S_un.S_addr = inet_addr(pchIP);
m_stAddress.sin_port = htons(iPort);
m_stTimeout.tv_sec = SOCK_TIMEOUT_SECONDS;
m_stTimeout.tv_usec = 0;
//connecting to server
long iMode = 1;
int iResult = ioctlsocket(m_hSocket, FIONBIO, &iMode);
connect(m_hSocket, (struct sockaddr *)&m_stAddress, sizeof(m_stAddress));
long iMode = 0;
iResult = ioctlsocket(m_hSocket, FIONBIO, &iMode);
fd_set stWrite;
FD_ZERO(&stWrite);
FD_SET(m_hSocket, &stWrite);
iResult = select(0, NULL, &stWrite, NULL, &m_stTimeout);
if((iResult > 0) && (FD_ISSET(m_hSocket, &stWrite)))
return true;
但是我无法弄清楚我在使用以下代码接收超时时缺少什么?如果服务器连接断开,它不会等待。它只是从 select 方法立即返回。 另外,如何编写带有超时的非阻塞套接字调用以进行套接字发送。
long iMode = 1;
int iResult = ioctlsocket(m_hSocket, FIONBIO, &iMode);
fd_set stRead;
FD_ZERO(&stRead);
FD_SET(m_hSocket, &stRead);
int iRet = select(0, &stRead, NULL, NULL, &m_stTimeout);
if ((iRet > 0) && (FD_ISSET(m_hSocket, &stRead)))
{
while ((iBuffLen-1) > 0)
{
int iRcvLen = recv(m_hSocket, pchBuff, iBuffLen-1, 0);
if (iRcvLen == SOCKET_ERROR)
{
return false;
}
else if (iRcvLen == 0)
{
break;
}
pchBuff += iRcvLen;
iBuffLen -= iRcvLen;
}
}
【问题讨论】:
-
您没有提供创建套接字的代码,所以我不知道它是什么类型的。尽管您似乎认为可以“断开连接”是有意义的,但是,它必须是某种类型的流套接字。在这种情况下,为什么您的程序在断开连接后还要继续尝试读取呢?在重新连接套接字之前,不会有任何数据出现,这不会自动发生。
-
我想我一旦收到 SOCKET_ERROR 就退出接收循环,这是错误的。至于单次读取,它可能会返回 SOCKET_ERROR 并且最终对于下一次读取它可能会报告成功,所以我想在这里我需要检查经过的时间。是这样吗?
-
使用写入和错误集:select(
, , , , timeout);