简体   繁体   中英

select() always returns 0

I seem to have a problem with select .

while(!sendqueue.empty())
{                                   
  if(!atms_connection.connected)
  {
    //print error message
    goto RECONNECT;
  }

  //select new
  FD_ZERO(&wfds);
  FD_SET(atms_connection.socket, &wfds);

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

  retval = select(atms_connection.socket + 1, NULL, &wfds, NULL, &tv);

  if (retval == -1) {
    printf("Select failed\n");                      
    break;
  }                     
  else if (retval) {
    printf("Sent a Message.\n"); 
  }
  else {
    //printf("retval value is %d\n",retval);
    printf("Server buffer is full, try again...\n");                        
    break;
  }
  n = write(atms_connection.socket, sendqueue.front().c_str(), sendqueue.front().length());
}

The function belongs to a thread, which, when it acquires the lock cleans a queue using select() and writes to socket in a loop until the queue is empty.

The first time the thread gets the lock it select() fine, but the second time it gets the lock and enters the while it always returns 0.

For the record, it used to work fine a while ago, and I haven't changed that code since then.

Selects returns 0 when it has a timeout. The following line specifies a time out to be 1 second.

tv.tv_sec = 1;

Usually a socket is ready for write and select would return immediately. However, if there is no room in the socket output buffer for the new data, select won't flag this socket as ready for write.

For example, this condition might happen when the other side of the connection is not calling recv/read . The amount of unconfirmed data grows and the buffer eventually becomes full. Since the timeout is fairly small, the select returns frequently with return value 0.

In addition to what is mentioned already, select api itself only tells whether a descriptor is ready. It can be used for both reading or writing depending upon what operation is chosen.

In your case, the "message sent" print seems to give the illusion the data is actually written, which is not the case. You have to make a write call on the descriptor which is returned as ready from select.

Select does not magically itself reads or writes to a buffer. In case you are a listening server, you call an accept or a read after select call returns successfully. In case you are a client and intend to write (like it appears in your case), you need to make an explicit write() or send() call.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM