[英]Using select() on listening socket
I want to open a port and wait for incoming connections, however I can't get select()
to work. 我想打开一个端口并等待传入连接,但是我无法使select()
正常工作。 I had it working with poll()
but I need select()
for portability. 我有它与poll()
一起工作,但是我需要select()
来实现可移植性。 What am I doing wrong? 我究竟做错了什么?
Code for waiting for the connection looks like this (I need to check for interruptions every 200ms): 等待连接的代码如下所示(我需要每200ms检查一次中断):
/* Wait for a descriptor */
int wait_for_fd(int fd){
int waitms = 200;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = waitms * 1000;
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
int active = 0;
while(active == 0){
active = select(fd+1, &rfds, NULL, NULL, &tv);
bail_for(active < 0, "select()");
if(pending_interrupt())
break;
}
return active;
}
And then my code to actually open a port and wait for a connection: 然后我的代码实际打开一个端口并等待连接:
int open_port(int port){
// define server socket
struct sockaddr_in serv_addr;
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(port);
//creates the listening socket
int listenfd = socket(AF_INET, SOCK_STREAM, 0);
bail_for(listenfd < 0, "socket()");
bail_for(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0, "bind()");
bail_for(listen(listenfd, 10) < 0, "listen()");
//each accept() is a new incoming connection
printf("Waiting for connetion on port %d...\n", port);
wait_for_fd(listenfd);
int connfd = accept(listenfd, NULL, NULL);
bail_for(connfd < 0, "accept()");
printf("Incoming connection!\n");
//do not allow additional client connetions
close(listenfd);
return connfd;
}
However wait_for_fd()
never returns (due to select always returning 0) even when a client is connecting. 但是,即使客户端正在连接, wait_for_fd()
也永远不会返回(由于选择总是返回0)。
This must be on every iteration: 这必须在每次迭代中:
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
Because rfds
is an in/out parameter for select()
. 因为rfds
是select()
的输入/输出参数。 It actually tells with it which fds were affected. 它实际上告诉它哪些fds受到了影响。
According to manpage of select
根据select
On exit, the sets are modified in place to indicate which file descriptors actually changed status. 退出时,对集合进行适当的修改,以指示实际更改状态的文件描述符。 Each of the three file descriptor sets may be specified as NULL if no file descriptors are to be watched for the corresponding class of events. 如果没有文件描述符针对相应的事件类进行监视,则可以将三个文件描述符集的每一个指定为NULL。
This means, that, when you have called select and no file-descriptors have changed, no file-descriptors are set in rfds
. 这意味着,当您调用select且未更改文件描述符时,不会在rfds
中设置rfds
。 Therefor you'll have to set them on each iteration 因此,您必须在每次迭代中设置它们
while(active == 0){
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
active = select(fd+1, &rfds, NULL, NULL, &tv);
bail_for(active < 0, "select()");
if(pending_interrupt())
break;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.