简体   繁体   English

select()始终返回0

[英]select() always returns 0

I seem to have a problem with select . 我似乎有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. 该函数属于一个线程,当它获取锁时,使用select()清除队列并在循环中写入套接字直到队列为空。

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. 第一次线程获得锁定时, select()很好,但是第二次获取锁定并进入while时它总是返回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. 超时时选择返回0。 The following line specifies a time out to be 1 second. 以下行指定超时为1秒。

tv.tv_sec = 1;

Usually a socket is ready for write and select would return immediately. 通常,套接字已准备好进行写入,而select将立即返回。 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. 但是,如果套接字输出缓冲区中没有空间用于新数据,则select不会将此套接字标记为准备写入。

For example, this condition might happen when the other side of the connection is not calling recv/read . 例如,当连接的另一端未调用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. 由于超时相当小,因此select经常返回值为0。

In addition to what is mentioned already, select api itself only tells whether a descriptor is ready. 除了已经提到的内容之外,选择api本身只会告诉描述符是否准备就绪。 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返回为ready。

Select does not magically itself reads or writes to a buffer. Select不会神奇地读取或写入缓冲区。 In case you are a listening server, you call an accept or a read after select call returns successfully. 如果您是侦听服务器,则在选择调用成功返回后调用accept或read。 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. 如果您是客户端并且打算编写(就像在您的情况下出现的那样),您需要进行显式的write()或send()调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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