select()似乎与cout / stdout绑定?

时间:2011-01-14 06:01:54

标签: linux sockets select

我正在使用select()来确定非阻塞连接何时连接,连接或连接失败;在Linux上使用TCP套接字。我的实际 TCP连接连接并正常工作,这只是为了检测它们的状态。

奇怪的是,我的代码总是首先给出了我认为的 CONNECTIONFAILED ..在cout(任何cout)之后,对select()的下一次调用给出了我认为的 CONNECTED 。套接字是否连接无关紧要。

我已经验证我使用了一个外观漂亮的套接字(在这种情况下它的int id是3,就像我说通过连接到监听netcat验证的实际连接确实很好)

我的顶级代码是

while(1)
{
  state = networking.connectionStatus(socketId);
  .. [cout would go here or not, as described above]
  if(state == CONNECTED) { // connected! }
  else .. // connecting, or connection failed code
}

我的选择代码,在这个非阻塞套接字上运行,传递给connectionStatus

myStateType connectionStatus(int socket)
{
  struct timeval tv; 
  tv.tv_sec = 0; tv.tv_usec = 0; // no timeout, immediately return from select()
  fd_set ourFdSet;

  FD_ZERO(&ourFdSet); // zero the set
  FD_SET(socket, &ourFdSet); // put our socket in to this set

  // Switch to figure out if we can write to our fd yet
  switch(select(socket + 1, NULL, &ourFdSet, NULL, &tv))
  {
    case -1: // connection failed, actual error from select()
      return CONNECTIONFAILED;
    break;
    case 0: // no fds ready to write, still connecting?? can someone verify this is true
      return CONNECTING;
    break;
    case 1: // now we have 1 fd ready to write, but look closer..
      // Examine our socket at the socket level for errors.. if < 0 then getsockopt fail
      if(getsockopt(socket, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
        return CONNECTIONFAILED;

      if(error == 0) return CONNECTED;
      if(error == EINPROGRESS) return CONNECTING;
      // otherwise, failure.. (a real error)
      return CONNECTIONFAILED;
      .. end of function ..

那么cout会在这里发生什么?这一切都在正确的轨道上吗?所有的手册页和互联网资源似乎都同意..

3 个答案:

答案 0 :(得分:3)

select()返回-1并不表示连接失败 - 它表示select()本身遇到错误。你应该返回一些不同的东西(或者至少在那条路径中放一个perror("select"))。这同样适用于getsockopt()失败。添加这些将有助于调试问题。

其余部分看起来很好 - 如果套接字不可写(select()返回零),则连接尝试仍在进行中。尽管你有相反的保证,但看起来你的文件描述符可能会混淆。

答案 1 :(得分:0)

绝对奇怪,所以'len'必须在传入之前设置为'sizeof len'(可能正确设置为sizeof错误,但它们是相同的)。

我没有意识到这是由getsockopt 读取的东西,我以为它只是一个返回值?返回错误中的内容..

感谢您的帮助

答案 2 :(得分:-1)

以上评论是正确的。

您在select上设置超时为零,以便立即返回。这是一个成功的返回值,但是所有FD_SET都可以保持清晰。

如果指定了0 w / a超时,则必须检查FD_SET上的FD_ISSET。如果没有设置,那么你知道你已经简单地跳过了选择超时并且套接字还没有准备好写入。这解释了你的CONNECTERROR,我确信那个状态下的getsockopt()并没有很好地定义。