C:具有超时功能的非阻塞套接字:如何检查是否发出了连接请求? [英] C : non blocking sockets with timeout : how to check if connection request was made?
问题描述
我想让一台服务器一次连接到一个客户端,而忽略连接到给定客户端时的连接请求.
I would like to have a server that connects to one client at a time, ignoring connection request when connected to a given client.
我还希望避免在侦听第一个客户端时锁定服务器,以便可以干净地终止程序.
I would also liked to avoid the server to get locked when listening for the first client, so that the program can be terminated cleanly.
显然,可以使套接字无阻塞: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#blocking
Apparently, sockets can be made non blocking: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#blocking
我相应地创建了我的套接字(为清楚起见,删除了错误管理代码)
I created my socket accordingly (error management code removed for clarity)
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));
从那时起,我不确定如何管理超时.以下代码不起作用,但是给出了我想要实现的想法.
From that point, I am not sure how to manage a timeout. The following code does not work, but gives an idea what I would like to achieve.
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;
}
}
到目前为止,我找到的所有解决方案都比我的情况更复杂(即一旦找到一个客户就不会忽略客户),而且看起来不必要地复杂.
Any solution I found so far were concerned about situation more complex than mine (i.e. not ignoring clients once one had been found) and seemed unnecessarily complicated.
编辑(接受答案后):
基于已接受的答案,这是我随附的代码:
Based on the accepted answer, here the code I came with:
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;
}
这可行,但是根据评论和回答,这不是可行的方法(显然,一种干净的方法可能与信号有关……)
This works, but according to comments and answer, this is not the way to go (apparently a clean way would have something to do with signals ...)
推荐答案
只需在侦听(非阻塞)套接字上调用accept()
.
Just call accept()
on the listening (non-blocking) socket.
如果积压中没有连接正在等待,则accept()
将立即返回-1
,并且errno
将被设置为EGAIN
或EWOULDBLOCK
.
If no connection was waiting in the backlog then accept()
would return immediately with -1
and errno
would be set to EGAIN
or EWOULDBLOCK
.
来自 man accept
:
错误
EAGAIN或EWOULDBLOCK
该套接字被标记为非阻塞,并且不存在任何可接受的连接. POSIX.1-2001允许在这种情况下返回任何一个错误,并且不需要这些常量具有相同的值,因此可移植应用程序应检查这两种可能性.
The socket is marked nonblocking and no connections are present to be accepted. POSIX.1-2001 allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibilities.
但是您显示的while
循环会实现忙等待,这非常昂贵.
However the while
-loop your are showing would implement busy-waiting, which is quite expensive.
所以为什么不让accept
通过简单地阻塞直到检测到传入连接来进行等待,所以.
So why not let accept
do the waiting by simply blocking until an incoming connection is detected.
要中断阻塞accept()
,只需向进程发送信号即可. accept()
然后将-1
和errno
设置为EINTR
返回.
To interupt the blocking accept()
just send the process a signal. accept()
then would return with -1
and errno
being set to EINTR
.
我想有一台连接到一个客户端的服务器
I would like to have a server that connects to one client
根据定义,始终是客户端连接到服务器.
By definitions it's always the client which connects to the server.
这篇关于C:具有超时功能的非阻塞套接字:如何检查是否发出了连接请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!