Reputation: 310
I'm using select to try and wait for an acknowledgement from another host on the network, but it always returns 0. I've seen other threads with similar questions, and their problem is always either they aren't resetting the fd_set, or they're not passing in the right value for the first parameter of select(). That can't be what's causing my problem, because I am resetting the fd_set, and the first parameter is ignored in windows, apparently, according to 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;
}
}
//there's more else if statements underneath, but it never goes there
No matter what, at this point it returns 0. I have seen the client and server send information to each other through the socket, so I don't think I'm sending to the wrong address on the client side. Here's the client side code for sending that packet that select() is waiting for:
buff[0] = _seqNum;
res = sendto(_socket, buff, 2, 0, (LPSOCKADDR) &sa_in, sizeof(SOCKADDR));
I can't be the only one whose ever had this problem, does anyone know how to address this?
Edit: Someone asked where _sockAddr is being filled out, so I'll include that here: Somewhere in there a ClienThread class is instantiated, and you can see a sockaddr_in being passed 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: Upon further debugging, I've found that the calls to sendto are reaching their intended target, since messages are received with calls to recvfrom, just not with select. However, I need to be able to use a non-blocking call.
Upvotes: 0
Views: 3006
Reputation: 596407
sendto()
is likely failing, but you are not checking it for any errors. sizeof(SOCKADDR)
is the wrong thing to use in the last parameter. Use sizeof(_sockAddr)
instead:
if (sendto(_clientSocket, buff, 2, 0, (LPSOCKADDR)&_sockAddr, sizeof(_sockAddr)) == SOCKET_ERROR)
{
cout << "Handshaking failed, error " << WSAGetLastError() << endl;
return false;
}
Make sure your _sockAddr
variable is a valid sockaddr_in
, sockaddr_in6
, or sockaddr_storage
, NOT a sockaddr
.
On a separate note, assuming _rttInfo.timeout
is expressed in milliseconds, your timeout.tv_usec
value is being calculated wrong. It should be like this instead:
struct timeval timeout;
timeout.tv_sec = _rttInfo.timeout / 1000;
timeout.tv_usec = (_rttInfo.timeout % 1000) * 1000;
Upvotes: 3
Reputation: 10613
Predictably, select times out because you ask for a timeout (based on whatever value rttInfo contains). If you want to wait longer, adjust rttInfo, or if you want to wait until something happens then specify a null value for the timeout.
Upvotes: 1
Reputation: 17085
Select times out because you set a timeout. If you want blocking operations you need timeout to be null: http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85).aspx
As you said, first parameter seems to be ignored. Something on the lines:
int res = select(0, &fds, NULL, NULL, NULL);
Upvotes: 0