我正在使用 select 尝试等待来自网络上另一台主机的确认,但它总是返回 0。我见过其他有类似问题的线程,他们的问题总是要么他们没有重置 fd_set,要么他们没有为 select() 的第一个参数传递正确的值。这不可能是导致我的问题的原因,因为我正在重置 fd_set,并且显然,根据 msdn 的说法,第一个参数在 windows 中被忽略了。
while(!done)
{
//send acknowledgment and sequence number
sendto(_clientSocket, buff, 2, 0, (LPSOCKADDR)&_sockAddr, sizeof(SOCKADDR));
//wait for acknowledgment
struct timeval timeout;
timeout.tv_sec = _rttInfo.timeout/1000;
timeout.tv_usec = _rttInfo.timeout * 1000;
fd_set fds;
FD_ZERO(&fds);
FD_SET(_clientSocket, &fds);
//wait for client to send an acknowledgement
//wait for the socket to be ready for reading
int res = select(0, &fds, NULL, NULL, &timeout);
int err = WSAGetLastError();
if(res == 0) //if timed out, retry
{
timedOutCount++;
if(timedOutCount >= MAX_TIMEOUTS)
{
cout << "Handshaking complete _" << endl;
return true;
}
else
{
cout << "Acknowledgement timed out, resending sequence number and acknowledgement" << endl;
continue;
}
}
//下面还有更多 else if 语句,但它永远不会出现在那里
无论如何,此时它返回0。我已经看到客户端和服务器通过套接字相互发送信息,所以我认为我没有发送到客户端的错误地址。这是发送 select() 正在等待的数据包的客户端代码:
buff[0] = _seqNum;
res = sendto(_socket, buff, 2, 0, (LPSOCKADDR) &sa_in, sizeof(SOCKADDR));
我不可能是唯一一个遇到过这个问题的人,有人知道如何解决这个问题吗?
编辑:有人问 _sockAddr 是在哪里填写的,所以我将在此处包括:在某处实例化了一个 ClienThread 类,您可以看到传入的 sockaddr_in。
while(true)
{
try
{
// Wait for connection
cout << "Waiting for incoming connection... ";
sockaddr_in clientSockAddr;
// int clientSockSize = sizeof(clientSockAddr);
// Listen in on the bound socket:
// hClientSocket = accept(hSocket,
// reinterpret_cast<sockaddr*>(&clientSockAddr),
// &clientSockSize);
unsigned char seqNum = 0;
int addrSize = sizeof(clientSockAddr);
//wait for a connection
int res=0;
//loop until we get a packet that's from someone new
bool blocking = true;
while(blocking)
{
res = recvfrom(hSocket, buff, strlen(buff), 0, (LPSOCKADDR)&clientSockAddr, &addrSize);
bool foundMatch = false;
//check if we're already handling this client. If so, keep blocking. Otherwise, break out of the loop
for(list<ClientThread*>::iterator it = clientList.begin(); it != clientList.end(); it++)
{
//compare network addresses
if((*it)->GetSockAddr().sin_addr.S_un.S_addr == clientSockAddr.sin_addr.S_un.S_addr)
{
foundMatch = true;
break;
}
}
if(!foundMatch)
{
blocking = false;
}
}
err = WSAGetLastError();
// Check if we can create a new client thread
if(res != SOCKET_ERROR && res != 0)
{
seqNum = (unsigned char) buff[0]; //get the sequence number for handshaking
cout << "accepted connection from: " << GetHostDescription(clientSockAddr) << endl;
//start a client thread, to handle requests from this client.
ClientThread* pThread = new ClientThread(hSocket, clientSockAddr, this, seqNum);
clientList.push_back(pThread);
pThread->start();
}
// if (hClientSocket==INVALID_SOCKET)
// throw "accept function failed.";
}
catch(char* ex)
{
cerr << "\nError: " << ex << endl;
bSuccess = false;
}
}
Edit2:经过进一步调试,我发现对 sendto 的调用达到了预期的目标,因为消息是通过调用 recvfrom 接收的,而不是通过 select。但是,我需要能够使用非阻塞调用。