I'm trying to wrap my head around calling select
on sockets and I can't understand what I'm doing wrong.
我试图绕着调用socket上的select来解决我无法理解我做错了什么。
setup_server_socket
calls bind
and listen
and sets the socket to nonblocking mode.
setup_server_socket调用bind和listen并将套接字设置为非阻塞模式。
The following code blocks on the select
call it seems, not moving forward to FD_ISSET
. I tried connecting a client and it seems to succeed but select
never returns anything.
以下代码在select调用上阻塞,而不是向前移动到FD_ISSET。我尝试连接客户端,它似乎成功但选择永远不会返回任何东西。
What's the proper way to do this?
这样做的正确方法是什么?
...
int listenfd = setup_server_socket( serverPort );
if( -1 == listenfd )
return 1;
fd_set read_fds;
FD_ZERO(&read_fds);
int fdmax = listenfd;
// loop forever
while( 1 )
{
if (select(fdmax+1, &read_fds, NULL,NULL,NULL) == -1){
perror("select");
exit(4);
}
for (int i = 0; i<= fdmax; i++){
printf("Testing: %d, %d\n", i, FD_ISSET(i,&read_fds));
}return 0;
...
2 个解决方案
#1
2
Read several times select(2), poll(2) (BTW, you should prefer poll
to the obsolete select
, which don't handle file descriptors bigger than __FD_SETSIZE
, i.e. 1024 on my Linux/Debian/x86-64 system).
多次读取select(2),poll(2)(BTW,你应该更喜欢轮询到过时的select,它不能处理大于__FD_SETSIZE的文件描述符,即我的Linux / Debian / x86-64系统上的1024)。
Then:
然后:
fd_set read_fds;
FD_ZERO(&read_fds);
int fdmax = listenfd;
FD_SET(listenfd, &read_fds);
should go inside the while(1)
loop, before calling select
. BTW, I recommend using poll
instead of select
应该在调用select之前进入while(1)循环。顺便说一句,我建议使用poll而不是select
Read also about the C10k problem
另请阅读有关C10k问题的信息
Don't forget that select
is changing its given fd_set
-s (and usually wants them to be non-empty)...
不要忘记select正在改变它给定的fd_set-s(并且通常希望它们非空)...
Perhaps use strace(1)
也许使用strace(1)
Read also Advanced Linux Programming (it is a free book that you could also read on paper, or download from several other places, e.g. this etc...)
另请阅读高级Linux编程(这是一本免费的书,您也可以在纸上阅读,或从其他几个地方下载,例如此等...)
#2
0
here is one (trimmed) example of using select()
这是使用select()的一个(修剪)示例
INT32 selectStatus; /* select() return code */
char tempreport[ 256 ] = {'\0'};
struct timeval tv;
fd_set fdread;
//fd_set fdwrite;
//fd_set fdexcep;
// note:
// must try to read report until no report available
// so have latest report in buffer
do
{
/* Note: timeout must be (re)set every time before call to select() */
tv.tv_sec = 1;
tv.tv_usec = 0;
FD_ZERO(&fdread);
FD_SET( FD, &fdread );
selectStatus = select(FD+1, &fdread, NULL, NULL, &tv);
switch( selectStatus )
{
case -1:
....
break;
case 0:
// timeout, I.E. nothing to read
....
break;
default: /* available to read */
memset(tempreport, 0x00, sizeof(tempreport) );
readStatus = read_UDP_socket( FD, tempreport, sizeof(tempreport), &readCount );
break;
} // end switch( selectStatus )
} while( (0 < selectStatus)&&(eRS_Success == readStatus ) );
// exit loop on select timeout or select error or read failure
notes:
笔记:
eRS_Success is an entry from an enum used for various return codes
read_UDP_socket() is a local function
#1
2
Read several times select(2), poll(2) (BTW, you should prefer poll
to the obsolete select
, which don't handle file descriptors bigger than __FD_SETSIZE
, i.e. 1024 on my Linux/Debian/x86-64 system).
多次读取select(2),poll(2)(BTW,你应该更喜欢轮询到过时的select,它不能处理大于__FD_SETSIZE的文件描述符,即我的Linux / Debian / x86-64系统上的1024)。
Then:
然后:
fd_set read_fds;
FD_ZERO(&read_fds);
int fdmax = listenfd;
FD_SET(listenfd, &read_fds);
should go inside the while(1)
loop, before calling select
. BTW, I recommend using poll
instead of select
应该在调用select之前进入while(1)循环。顺便说一句,我建议使用poll而不是select
Read also about the C10k problem
另请阅读有关C10k问题的信息
Don't forget that select
is changing its given fd_set
-s (and usually wants them to be non-empty)...
不要忘记select正在改变它给定的fd_set-s(并且通常希望它们非空)...
Perhaps use strace(1)
也许使用strace(1)
Read also Advanced Linux Programming (it is a free book that you could also read on paper, or download from several other places, e.g. this etc...)
另请阅读高级Linux编程(这是一本免费的书,您也可以在纸上阅读,或从其他几个地方下载,例如此等...)
#2
0
here is one (trimmed) example of using select()
这是使用select()的一个(修剪)示例
INT32 selectStatus; /* select() return code */
char tempreport[ 256 ] = {'\0'};
struct timeval tv;
fd_set fdread;
//fd_set fdwrite;
//fd_set fdexcep;
// note:
// must try to read report until no report available
// so have latest report in buffer
do
{
/* Note: timeout must be (re)set every time before call to select() */
tv.tv_sec = 1;
tv.tv_usec = 0;
FD_ZERO(&fdread);
FD_SET( FD, &fdread );
selectStatus = select(FD+1, &fdread, NULL, NULL, &tv);
switch( selectStatus )
{
case -1:
....
break;
case 0:
// timeout, I.E. nothing to read
....
break;
default: /* available to read */
memset(tempreport, 0x00, sizeof(tempreport) );
readStatus = read_UDP_socket( FD, tempreport, sizeof(tempreport), &readCount );
break;
} // end switch( selectStatus )
} while( (0 < selectStatus)&&(eRS_Success == readStatus ) );
// exit loop on select timeout or select error or read failure
notes:
笔记:
eRS_Success is an entry from an enum used for various return codes
read_UDP_socket() is a local function