【发布时间】:2017-07-23 13:05:00
【问题描述】:
我想打开一个端口并等待传入连接,但是我无法让select() 工作。我让它与poll() 一起工作,但我需要select() 以实现可移植性。我做错了什么?
等待连接的代码如下所示(我需要每 200 毫秒检查一次中断):
/* 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)。
【问题讨论】:
-
select的便携性?可移植到什么? PDP-11?select速度非常慢,除非你做了一些非常奇怪、不可移植和未记录的黑客行为,否则当你打开超过 X(通常为 1024)个文件描述符时,你将开始崩溃和/或覆盖随机内存。select已经死了,如果不是 15 年前,至少应该从标准中删除 10 年。请重新考虑。在新软件中使用select就像在新加密中使用 MD5。 -
Windows (mingw-w64) 没有
poll()。 -
@Art 可移植到 POSIX。
poll在性能方面并没有好多少,并且不支持原子解锁信号。 1024 的限制几乎不是问题,如果你有那么多文件描述符,你应该把 POSIX 放在一边,作为 O(1) 的替代方案,但如果你只有几个文件描述符,这样的替代方案就过分了。
标签: c linux sockets select bind