C++ 套接字选择()在Windows中工作,在Linux中超时
我正在将一个windows网络应用程序移植到linux,并且在linux上遇到了select调用超时问题。当我使用数据包嗅探器检查客户机是否已经发送了数据时,以下函数会阻塞整个超时值并返回C++ 套接字选择()在Windows中工作,在Linux中超时,c++,linux,sockets,select,C++,Linux,Sockets,Select,我正在将一个windows网络应用程序移植到linux,并且在linux上遇到了select调用超时问题。当我使用数据包嗅探器检查客户机是否已经发送了数据时,以下函数会阻塞整个超时值并返回 int recvTimeOutTCP( SOCKET socket, long sec, long usec ) { struct timeval timeout; fd_set fds;. timeout.tv_sec = sec; timeout.tv_usec = usec; FD
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);
}
int recvTimeOutTCP(套接字,长秒,长usec)
{
结构timeval超时;
fd_设置fds;。
timeout.tv_sec=秒;
timeout.tv_usec=usec;
FD_零(&fds);
FD_装置(插座和fds);
//可能的返回值:
//-1:发生错误
//0:超时
//>0:准备好读取的数据
cerr我认为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);
(…)的第一个参数是要在集合中签入的文件描述符的数目。您的调用告诉它只查看文件描述符0,这几乎肯定不是socket设置的值。在Windows上选择将忽略第一个参数。从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_集是一个位数组(最初它只是一个int,但之后您只能查看进程的前16个io)。在windows中,fd_集是一个插槽数组,前面有一个长度(这就是为什么windows不需要知道要查看多少位)
poll()函数可以在linux上查看一组记录,并具有其他优点,因此它比select()更好
@jamessan啊,是的,我的意思是;)对。int-select(int-nfds,fd_-set*readfds,fd_-set*writefds,fd_-set*exceptfds,struct-timeval*timeout);
其中nfds是三个集合中编号最高的文件描述符,加上1。
Windows中的实现忽略了第一个参数!酷!无需暗示-这在Microsoft的select()
文档中有明确说明:感谢您提供的信息,这个poll()函数是否可能跨平台?嗯,在Linux上,您真的想使用epoll,最好是在边缘触发模式下。
int recvTimeOutTCP( SOCKET socket, long msec )
{
int iret ;
struct polldf sockpoll ;
sockpoll.fd= socket ;
sockpoll.events= POLLIN ;
return poll(& sockpoll, 1, msec) ;
}