繁体   English   中英

套接字select()在Windows中工作,在Linux中超时

[英]Socket select() works in Windows and times out in Linux

我正在将Windows网络应用程序移植到linux,并且在linux上选择调用时遇到超时问题。 以下函数将阻止整个超时值,并在我用包嗅探器检查客户端已发送数据时返回。

int recvTimeOutTCP( SOCKET socket, long sec, long usec )
{
  struct timeval timeout;
  fd_set fds;.

  timeout.tv_sec = sec;
  timeout.tv_usec = usec;
  FD_ZERO( &fds );
  FD_SET( socket, &fds );

  // Possible return values:
  // -1: error occurred
  // 0: timed out
  // > 0: data ready to be read
  cerr << "Waiting on fd " << socket << endl;
  return select(1, &fds, 0, 0, &timeout);
}

我认为select()的第一个参数应该是socket+1

您确实应该使用其他名称,因为socket也用于其他用途。 通常使用sock

从选择的手册页中:

int select(int nfds,
           fd_set* restrict readfds,
           fd_set* restrict writefds,
           fd_set* restrict errorfds, 
           struct timeval* restrict timeout);

在每个集合中检查第一个nfds描述符; 也就是说,检查描述符集中从0到nfds-1的描述符。

因此,要选择的第一个参数应该是socket + 1。

return select(socket + 1, &fds, 0, 0, &timeout);

Windows上的select忽略第一个参数。 从MSDN:

C++
int select(
  __in     int nfds,
  __inout  fd_set *readfds,
  __inout  fd_set *writefds,
  __inout  fd_set *exceptfds,
  __in     const struct timeval *timeout
);

Parameters

nfds [in]

    Ignored. The nfds parameter is included only for
    compatibility with Berkeley sockets.
...

问题是Linux中的fd_set是一个位数组(起初它只是一个int,但随后您只能观看进程的前16个io)。 在Windows中,fd_set是一个套接字数组,其长度在前面(这就是为什么Windows不需要知道要监视多少位的原因)。

poll()函数接受一系列记录以在Linux上观看,并且具有其他优点,这使其比select()更好。

int recvTimeOutTCP( SOCKET socket, long msec )
{
    int iret ;
    struct polldf   sockpoll ;

    sockpoll.fd= socket ;
    sockpoll.events= POLLIN ;

    return poll(& sockpoll, 1, msec) ;
}   

选择的第一个参数(...)是要在集合中检查的文件描述符的数量。 您的呼叫告诉它仅查看文件描述符0,这几乎可以肯定不是套接字设置的内容。

暂无
暂无

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

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