我正在开发一个tcp客户端应用程序,它将发送并等待来自服务器的响应数据。
我的协议是:客户端将发送一些数据,它将等待最多3秒从服务器获取相应的ack。如果在上述时间段内未能收到相同的内容,则会再尝试两次。现在使用下面的代码我正在检查接收是否失败了3个精确的秒。
我将套接字设置为非阻塞模式,然后首先通过select()检查可读性模式。我是否真的需要这个select()调用,因为客户端根本不处于侦听模式,它通过以下方法进行通信:
现在我有以下代码的两个问题。我应该使用select(),我是否正确使用GetTickCount()检查超时?
bool CTCPCommunication::ReceiveSocketData(char* pchBuff, int iBuffLen)
{
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;
}
pchBuff += iRcvLen;
iBuffLen -= iRcvLen;
}
}
else
{
WRITELOG("Failed to socket call 'select' inside 'ReceiveSocketData' with error: %d", WSAGetLastError());
bReturn = false;
}
SetNonBlockingMode(false);
return bReturn;
}