c tcp套接字非阻塞接收超时
c tcp socket non blocking receive timeout
正在尝试编写一个客户端,该客户端将尝试在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;
}
}
要选择的第一个参数不应为0。select的正确用法可在此处找到:http://developerweb.net/viewtopic.php?id=2933
第一个参数应该是套接字的最大值+1,如果是非阻塞的,则将中断的系统调用考虑在内:
/* Call select() */
do {
FD_ZERO(&readset);
FD_SET(socket_fd, &readset);
result = select(socket_fd + 1, &readset, NULL, NULL, NULL);
} while (result == -1 && errno == EINTR);
这只是您可能还需要timeout参数的示例代码。如果你能得到EINTR,这将使你所需的逻辑复杂化,因为如果你得到EINTR,你必须再次打同样的电话,但还有剩余的时间等待。
我认为对于非阻塞模式,需要检查recv()失败以及超时值。这意味着firstselect()将返回套接字是否准备好接收数据。如果是,它将继续,否则它将休眠,直到select()方法调用行上超时为止。但是,如果在读取循环中由于某些不确定的情况导致接收失败,我们需要手动检查套接字错误和最大超时值。如果套接字错误持续并且超时,我们需要中断它。
我已经完成了非阻塞模式下的接收超时逻辑。如果我错了,请纠正我。
bool bReturn = true;
SetNonBlockingMode(true);
//check whether the socket is ready to receive
fd_set stRead;
FD_ZERO(&stRead);
FD_SET(m_hSocket, &stRead);
int iRet = select(0, &stRead, NULL, NULL, &m_stTimeout);
DWORD dwStartTime = GetTickCount();
DWORD dwCurrentTime = 0;
//if socket is not ready this line will be hit after 3 sec timeout and go to the end
//if it is ready control will go inside the read loop and reads data until data ends or
//socket error is getting triggered continuously for more than 3 secs.
if ((iRet > 0) && (FD_ISSET(m_hSocket, &stRead)))
{
while ((iBuffLen-1) > 0)
{
int iRcvLen = recv(m_hSocket, pchBuff, iBuffLen-1, 0);
dwCurrentTime = GetTickCount();
if ((iRcvLen == SOCKET_ERROR) && ((dwCurrentTime - dwStartTime) >= SOCK_TIMEOUT_SECONDS * 1000))
{
bReturn = false;
break;
}
else if (iRcvLen == 0)
{
break;
}
pchBuff += iRcvLen;
iBuffLen -= iRcvLen;
}
}
SetNonBlockingMode(false);
return bReturn;
相关文章:
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 是否可以用"iostream"包装现有的TCP/OOpenSSL会话
- C++减少modbus_connect超时
- 没有超时的C++条件变量
- 我可以与 python 服务器而不是 c++ 客户端建立 tcp/ip 套接字吗?
- 提升 Asio TCP 服务器 处理多个客户端
- 如何在C++(VS2010)中设置超时读取USB端口?
- 通过TCP的PvP通信问题
- C++卷曲柱在curl_easy_perform超时
- C++ boost::asio::ip::tcp::acceptor 有时不接受连接器?
- 如何在Qt 4.8中阻止/忽略/丢弃早于特定超时的用户输入事件
- AWS IoT 开发工具包:通过 TCP 端口 443 使用 MQTT
- 接受超时的 TCP 连接
- TCP 连接中的超时,没有数据交换
- c tcp套接字非阻塞接收超时
- TCP 数据记录超时对我不起作用
- TCP服务器为每个客户端设置超时时间
- C++中TCP重传超时检测
- Windows TCP 套接字超时C++