我想打开一个端口并等待传入的连接,但是我无法让select()
工作。我让它与poll()
一起使用,但我需要select()
才能实现可移植性。我做错了什么?
等待连接的代码如下所示(我需要每隔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;
}
然后我的代码实际打开一个端口并等待连接:
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;
}
但是,即使客户端正在连接,wait_for_fd()
也永远不会返回(由于select始终返回0)。
答案 0 :(得分:4)
必须在每次迭代时都这样:
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
因为rfds
是select()
的输入/输出参数。它实际上告诉它哪些fds受到了影响。
答案 1 :(得分:2)
根据select
退出时,会对这些集进行修改,以指示哪些文件描述符实际更改了状态。如果没有为相应的事件类观察文件描述符,则可以将三个文件描述符集中的每一个指定为NULL。
这意味着,当您调用select并且没有更改文件描述符时,rfds
中没有设置文件描述符。因此,您必须在每次迭代时设置它们
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;
}