Почему select () всегда истекает? (окна)

Я использую select, чтобы попытаться дождаться подтверждения от другого хоста в сети, но он всегда возвращает 0. Я видел другие потоки с похожими вопросами, и их проблема всегда в том, что они не сбрасывают fd_set, или они не передают правильное значение для первого параметра select (). Это не может быть причиной моей проблемы, потому что я сбрасываю fd_set, а первый параметр игнорируется в Windows, по-видимому, согласно msdn.

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;
}
}

// есть еще что-то, если заявления внизу, но это никогда не идет туда

Независимо от того, что в этот момент он возвращает 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. Однако мне нужно иметь возможность использовать неблокирующий вызов.

0

Решение

sendto() Вероятно, сбой, но вы не проверяете его на наличие ошибок. sizeof(SOCKADDR) неправильно использовать в последнем параметре. использование sizeof(_sockAddr) вместо:

if (sendto(_clientSocket, buff, 2, 0, (LPSOCKADDR)&_sockAddr, sizeof(_sockAddr)) == SOCKET_ERROR)
{
cout << "Handshaking failed, error " << WSAGetLastError() << endl;
return false;
}

Убедитесь, что ваш _sockAddr переменная является действительной sockaddr_in, sockaddr_in6, или же sockaddr_storage, НЕ sockaddr,

На отдельной ноте, предполагая _rttInfo.timeout выражается в миллисекундах, ваш timeout.tv_usec значение рассчитывается неправильно. Вместо этого должно быть так:

struct timeval timeout;
timeout.tv_sec = _rttInfo.timeout / 1000;
timeout.tv_usec = (_rttInfo.timeout % 1000) * 1000;
3

Другие решения

Как и ожидалось, выберите время ожидания, потому что вы запрашиваете время ожидания (в зависимости от того, какое значение содержит rttInfo). Если вы хотите подождать дольше, настройте rttInfo, или если вы хотите подождать, пока что-то не произойдет, укажите нулевое значение для тайм-аута.

1

Выберите время ожидания, потому что вы установили время ожидания. Если вы хотите блокировать операции, вам нужно, чтобы время ожидания было нулевым: http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85).aspx

Как вы сказали, первый параметр, кажется, игнорируется. Что-то на линии:

int res = select(0, &fds, NULL, NULL, NULL);
0
По вопросам рекламы [email protected]