[英]Socket select() works in Windows and times out in Linux
I'm porting a windows network application to linux and faced a timeout problem with select call on linux. 我正在将Windows网络应用程序移植到linux,并且在linux上选择调用时遇到超时问题。 The following function blocks for the entire timeout value and returns while I checked with a packet sniffer that client has already sent the data.
以下函数将阻止整个超时值,并在我用包嗅探器检查客户端已发送数据时返回。
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);
}
I think the first parameter to select()
should be socket+1
. 我认为
select()
的第一个参数应该是socket+1
。
You really should use another name as socket
also is used for other things. 您确实应该使用其他名称,因为
socket
也用于其他用途。 Usually sock
is used. 通常使用
sock
。
From the man page of select: 从选择的手册页中:
int select(int nfds,
fd_set* restrict readfds,
fd_set* restrict writefds,
fd_set* restrict errorfds,
struct timeval* restrict timeout);
The first nfds descriptors are checked in each set;
在每个集合中检查第一个nfds描述符; ie, the descriptors from 0 through nfds-1 in the descriptor sets are examined.
也就是说,检查描述符集中从0到nfds-1的描述符。
Thus the first parameter to select should be socket + 1. 因此,要选择的第一个参数应该是socket + 1。
return select(socket + 1, &fds, 0, 0, &timeout);
select
on Windows ignores the first parameter. Windows上的
select
忽略第一个参数。 From MSDN: 从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.
...
The issue is that the fd_set in linux is a bit array ( originally it was just a int, but then you could only watch the first 16 io's of your process ). 问题是Linux中的fd_set是一个位数组(起初它只是一个int,但随后您只能观看进程的前16个io)。 In windows fd_set is an array of sockets with a length at the front (which is why windows doesn't need to know how many bits to watch).
在Windows中,fd_set是一个套接字数组,其长度在前面(这就是为什么Windows不需要知道要监视多少位的原因)。
The poll() function takes an array of records to watch on linux and has other benefits which make it a better choice than select(). 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) ;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.