Set timeout for winsock recvfrom

43,256

Solution 1

I looked into the select function and as laura said I should do and got it to work real easily! Thanks!

fd_set fds ;
int n ;
struct timeval tv ;

// Set up the file descriptor set.
FD_ZERO(&fds) ;
FD_SET(mHandle, &fds) ;

// Set up the struct timeval for the timeout.
tv.tv_sec = 10 ;
tv.tv_usec = 0 ;

// Wait until timeout or data received.
n = select ( mHandle, &fds, NULL, NULL, &tv ) ;
if ( n == 0)
{ 
  printf("Timeout..\n");
  return 0 ;
}
else if( n == -1 )
{
  printf("Error..\n");
  return 1;   
}

int length = sizeof(remoteAddr);

recvfrom(mHandle, buffer, 1024, 0, (SOCKADDR*)&remoteAddr, &length); 

Solution 2

I tried it by passing it like the folloing

     int iTimeout = 1600;
     iRet = setsockopt( pSapManager->m_cSocket,
                        SOL_SOCKET,
                        SO_RCVTIMEO,
                        /*
                        reinterpret_cast<char*>(&tv),
                        sizeof(timeval) );
                        */
                        (const char *)&iTimeout,
                        sizeof(iTimeout) );

and run it!!

Solution 3

WINDOWS: Timeout value is a DWORD in milliseconds, address passed to setsockopt() is const char *

LINUX: Timeout value is a struct timeval, address passed to setsockopt() is const void *

Source: http://forums.codeguru.com/showthread.php?t=353217

Solution 4

I'm guessing Windows from the WSASocket() call. If so you're passing the timeout incorrectly.

MSDN says that SO_RCVTIMEO takes an int param that specifies the timeout in ms.

Share:
43,256
Cory Carlson
Author by

Cory Carlson

Updated on July 09, 2022

Comments

  • Cory Carlson
    Cory Carlson almost 2 years

    I'm trying to set up a blocking socket to timeout after 16 ms of trying to recvfrom() on a port. Platform is Windows. I've looked at tons of examples online and it seems really simple I just can't seem to get it to work. Any help would be appreciated!

    #include <winsock2.h>
    #include <string>
    
    #pragma comment(lib, "ws2_32.lib")
    
    #define PORT_NUM 8001
    
    int main(void)
    {
      std::string localIP;
      sockaddr_in localAddr;
      sockaddr_in remoteAddr;
      hostent* localhost;
      char buffer[1024];
      WSADATA wsData;
    
      int result = WSAStartup(MAKEWORD(2,2), &wsData);  // winsock version 2
    
      localhost = gethostbyname("");
      localIP   = inet_ntoa(*(in_addr*)*localhost->h_addr_list);
    
      localAddr.sin_family       = AF_INET;
      localAddr.sin_port         = htons(PORT_NUM);             // Set Port Number
      localAddr.sin_addr.s_addr  = inet_addr(localIP.c_str());  // Set IP Address
    
      int mHandle = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);
    
      if(mHandle == INVALID_SOCKET)
        return 1;
    
    
      if(bind(mHandle, (SOCKADDR*)&localAddr, sizeof(localAddr)) == SOCKET_ERROR)
        return 1;
    
      timeval tv;
      tv.tv_sec  = 0;
      tv.tv_usec = 1600;
    
        // Set Timeout for recv call
      if(setsockopt(mHandle, SOL_SOCKET, SO_RCVTIMEO, 
                    reinterpret_cast<char*>(&tv), sizeof(timeval)))
        return 1;
    
      int length = sizeof(remoteAddr);
    
      // <-- Blocks here forever
      recvfrom(mHandle, buffer, 1024, 0, (SOCKADDR*)&remoteAddr, &length);  
    
      return 0;
    }
    
    /*  I've also tried passing the time like so:
    int ms = 16;
    
    if(setsockopt(mHandle, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<char*>(&ms), sizeof(int)))
      return 1; */