使用 select() 检查套接字在数据存在时返回 0

check on socket with select() returns 0 when data is present

本文关键字:存在 数据 返回 套接字 select 检查 使用      更新时间:2023-10-16

我的套接字类已经工作了一段时间了,但我想使用 select() 添加一个超时。 看起来很简单,但我总是从 select() 返回 0。 我什至删除了 select() 检查,因此无论 select() 如何它都会读取数据并且数据被读取,但 select() 仍然报告数据不存在。 关于如何让 select() 停止对我撒谎的任何线索? 我还将套接字设置为非阻塞。 谢谢。

法典:

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 << "]nn";
// Check
if (FD_ISSET(m_sock,&Sockets))
  std::cout << "nFD_ISSET(m_sock,&Sockets) is truenn";
else
  std::cout << "nFD_ISSET(m_sock,&Sockets) is falsenn";
// 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 READn";
  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::recvn";
      return 0;
  }
  else if ( status == 0 )
  {
      return 0;
  }
  else
  {
      s = buf;
      return status;
  }
}
// If data not present
else
{
std::cout << "nDATA WAS NOT READY, TIMEOUTn";
return 0;
}

正如您已经发现的那样,您对select的调用不正确。尽管第一个参数在许多形式的文档中被命名为nfds,但它实际上比传递给select的任何fd_set所持有的最大文件描述符编号多一个。在这种情况下,由于您只传入一个文件描述符,因此调用应该是:

retval = select(m_sock + 1, &Sockets, NULL, NULL, &tv);
如果您有任意数量的套接字,

则在不同的线程中处理每个套接字,您可能会发现我对这个问题的回答是更好的方法。

哎呀。 看起来我忘了设置 select() 的 int nfds:

现在工作得很好。