4

I've had my socket class working for a while now, but I wanted to add a timeout using select(). Seems pretty straight forward but I always have 0 returned from select(). I've even removed the select() check so it reads data regardless of select() and the data gets read, but select() still reports that data is not present. Any clue on how to get select() to stop lying to me? I've also set the socket to non-blocking. Thanks.

Code:

char buf [ MAXRECV + 1 ];

s = "";

memset ( buf, 0, MAXRECV + 1 );


struct timeval tv;
int retval;

fd_set Sockets;
FD_ZERO(&Sockets);
FD_SET(m_sock,&Sockets);

// Print sock int for sainity
std::cout << "\nm_sock:" << m_sock << "\n";

tv.tv_sec = 1;
tv.tv_usec = 0;

retval = select(1, &Sockets, NULL, NULL, &tv);
std::cout << "\nretval is :[" << retval << "]\n\n";

// Check
if (FD_ISSET(m_sock,&Sockets))
  std::cout << "\nFD_ISSET(m_sock,&Sockets) is true\n\n";
else
  std::cout << "\nFD_ISSET(m_sock,&Sockets) is false\n\n";

// If error occurs
if (retval == -1)
{
  perror("select()");
  std::cout << "\nERROR IN SELECT()\n";
}
// If data present
else if (retval)
{
  std::cout << "\nDATA IS READY TO BE READ\n";
  std::cout << "recv ( m_sock, buf, MAXRECV, 0)... m_sock is " << m_sock << "\n";
  int status = recv ( m_sock, buf, MAXRECV, 0 );

  if ( status == -1 )
  {
      std::cout << "status == -1   errno == " << errno << "  in Socket::recv\n";
      return 0;
  }
  else if ( status == 0 )
  {
      return 0;
  }
  else
  {
      s = buf;
      return status;
  }
}
// If data not present
else
{
std::cout << "\nDATA WAS NOT READY, TIMEOUT\n";
return 0;
}
Matt
  • 653
  • 1
  • 8
  • 20

2 Answers2

4

Your call to select is incorrect, as you have already discovered. Even though the first parameter is named nfds in many forms of documentation, it is actually one more than the largest file descriptor number held by any of the fd_sets passed to select. In this case, since you are only passing in one file descriptor, the call should be:

retval = select(m_sock + 1, &Sockets, NULL, NULL, &tv);

If you have an arbitrary number of sockets you are handling each in a different thread, you might find my answer to this question a better approach.

Community
  • 1
  • 1
jxh
  • 69,070
  • 8
  • 110
  • 193
  • Yes I totally agree, much better. My setup right now is dealing with 2 sockets, one sync and one async. But I'm defiantly going to rewrite to implement your approach. – Matt Jun 19 '12 at 19:35
0

Whoops. Looks like I forgot to set select()'s int nfds:

working good now.

Matt
  • 653
  • 1
  • 8
  • 20
  • 1
    This is wrong, the first argument to `select()` should not be `FD_SETSIZE` in general, and in particular not for this code. See user315052's answer. – unwind Jun 19 '12 at 15:41