C:具有超时的非阻塞套接字:如何检查是否发出了连接请求?

我希望有一台服务器一次连接到一个客户端,在连接到给定客户端时忽略连接请求。

我还希望避免服务器在侦听第一个客户端时被锁定,以便程序可以干净地终止。

显然,套接字可以是非阻塞的: http : //beej.us/guide/bgnet/output/html/singlepage/bgnet.html#blocking

我相应地创建了我的套接字(为清楚起见,删除了错误管理

int sockfd; struct sockaddr_in self; sockfd = socket(AF_INET, SOCK_STREAM, 0)); fcntl(sockfd, F_SETFL, O_NONBLOCK); // making this socket non blocking bzero(&self, sizeof(self)); self.sin_family = AF_INET; self.sin_port = htons(port); self.sin_addr.s_addr = inet_addr("127.0.0.1"); // allowing connection from localhost only. bind(sockfd, (struct sockaddr*)&self, sizeof(self)); 

从那时起,我不确定如何管理超时。 以下代码不起作用,但提供了我想要实现的内容。

 int client_found = 0; while ( no_stop_signal && client_found==0 ) { listen(sockfd,1); if ( ** something that tells me nobody was requesting connection ** ) { usleep(10); } else { client_found = 1; } } 

到目前为止我发现的任何解决方案都关注比我更复杂的情况(即一旦发现一个人就不会忽视客户)并且看起来不必要地复杂化。

编辑(接受答案后):

基于接受的答案,这里是我带来的代码:

 static inline int wait_for_client_to_connect(int sockfd, int* server_run){ int client_found = 0; int clientfd = 0; struct sockaddr_in client_addr; int addrlen=sizeof(client_addr); if ( listen(sockfd,1) != 0 ) return -1; while ( client_found==0 && *server_run==1 ) { clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen); if ( clientfd < 0 ) { clientfd = 0; if (errno==EAGAIN || errno==EWOULDBLOCK) usleep(10); // nobody connected, wait for request else return -1; // something wrong, send error } else { // client found, configuring socket and exit client_found=1; int nodelay_flag = 1; setsockopt(clientfd, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay_flag, sizeof(int)); // disable nagle algorithm } } return clientfd; } 

这是有效的,但根据评论和回答,这不是要走的路(显然干净的方式会与信号有关…)

只需在侦听(非阻塞)套接字上调用accept()

如果在积压中没有等待连接,则accept()将立即返回-1并且errno将设置为EGAINEWOULDBLOCK

man accept

错误

EAGAIN或EWOULDBLOCK

套接字标记为非阻塞,并且不存在可接受的连接。 POSIX.1-2001允许在这种情况下返回错误,并且不要求这些常量具有相同的值,因此便携式应用程序应检查这两种可能性。


然而你正在展示的while -loop会实现忙碌等待,这非常昂贵。

那么为什么不让accept通过简单阻塞来等待直到检测到传入连接。

为了阻断阻塞accept()只需向进程发送一个信号。 accept()然后返回-1并将errno设置为EINTR


我想有一个连接到一个客户端的服务器

根据定义,它始终是连接到服务器的客户端。