[英]In socket programming using C language, how to set time limit on server for accepting client to establish connection?
I'm developing an application which involves 1 client and 1 server.我正在开发一个涉及 1 个客户端和 1 个服务器的应用程序。
I want the server to listen for only 5 seconds for a connection.我希望服务器只侦听 5 秒钟的连接。 If the client is not attempting to establish a connection then the sever should stop listening and return an error message.
如果客户端未尝试建立连接,则服务器应停止侦听并返回错误消息。 If the client attempts to establish a connection then the server should accept the connection.
如果客户端尝试建立连接,则服务器应接受该连接。
The server is listening forever if the client is not making an attempt to establish a connection.如果客户端未尝试建立连接,则服务器将永远侦听。 I want the server to listen for only 5 seconds, how can this be achieved?
我想让服务器只监听 5 秒,这怎么实现?
This is the server-side output - server is waiting for client forever:这是服务器端输出 - 服务器永远等待客户端:
void reception(){
int sockfd, connfd, len;
struct sockaddr_in servaddr, cli;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);
if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
printf("socket bind failed...\n");
exit(0);
}
else
printf("Socket successfully binded..\n");
if ((listen(sockfd, 5)) != 0) {
printf("Listen failed...\n");
exit(0);
}
else
printf("Server listening..\n");
len = sizeof(cli);
connfd = accept(sockfd, (SA*)&cli, &len);
/*
Some function should be added at this point to
stop the server from listening after 5 seconds
*/
if (connfd < 0) {
printf("server acccept failed...\n");
exit(0);
}
else
printf("server acccept the client...\n");
receive(connfd);
close(sockfd);
}
You are using the listening socket in blocking mode, so accept()
will block the calling thread until a client connects.您正在以阻塞模式使用侦听套接字,因此
accept()
将阻塞调用线程,直到客户端连接为止。 To use a timeout, call select()
or (e)poll()
first to wait for the listening socket to enter a readable state indicating a connection is pending BEFORE you then call accept()
.要使用超时,
select()
调用select()
或(e)poll()
以等待侦听套接字进入可读状态,指示连接挂起,然后再调用accept()
。
For example:例如:
...
fd_set rds;
FD_ZERO(&rds);
FD_SET(sockfd, &rds);
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
int res;
if ((res = select(sockfd+1, &rds, NULL, NULL, &timeout)) <= 0)
{
if (res < 0)
printf("select failed...\n");
else
printf("Time out...\n");
exit(0);
}
connfd = accept(sockfd, (SA*)&cli, &len);
...
...
struct pollfd pfd;
pfd.fd = sockfd;
pfd.events = POLLIN;
pfd.revents = 0;
int res;
if ((res = poll(&pfd, 1, 5000)) <= 0)
{
if (res < 0)
printf("poll failed...\n");
else
printf("Time out...\n");
exit(0);
}
connfd = accept(sockfd, (SA*)&cli, &len);
...
int epfd = epoll_create(1);
if (epfd < 0)
{
printf("epoll_create failed...\n");
exit(0);
}
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = sockfd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev) < 0)
{
printf("epoll_ctl failed...\n");
exit(0);
}
struct epoll_event event;
int res;
if ((res = epoll_wait(epfd, &event, 1, 5000)) <= 0)
{
if (res < 0)
printf("epoll_ctl failed...\n");
else
printf("Time out...\n");
exit(0);
}
close(epfd);
connfd = accept(sockfd, (SA*)&cli, &len);
...
Either way, note that there is a very small race condition created by these scenarios.无论哪种方式,请注意这些场景会产生非常小的竞争条件。 If the client connects and then disconnects before
accept()
is called, accept()
may block waiting for a new pending connection, or it may return a valid file descriptor that fails on subsequent I/O calls.如果客户端连接,然后断开连接之前
accept()
被调用时, accept()
可能会阻止等待新挂起的连接,或者它可能返回后续I / O调用失败,一个有效的文件描述符。 There is no guarantee one way or the other.无法保证以一种方式或另一种方式。
To solve the race condition, you can either:要解决竞争条件,您可以:
put the listening socket into non-blocking mode.将侦听套接字置于非阻塞模式。 If
select()
reports the listening socket has a pending connection, but accept()
is not able to accept it right away, then you can act accordingly.如果
select()
报告侦听套接字有一个挂起的连接,但accept()
无法立即接受它,那么您可以采取相应的行动。
use accept()
on a listening socket in blocking mode, as you originally were, but use alert()
to schedule accept()
to be interrupted if it doesn't exit before 5 seconds have elapsed.在阻塞模式下在侦听套接字上使用
accept()
,就像您最初使用的那样,但是如果它在 5 秒内没有退出,则使用alert()
安排accept()
被中断。 See this answer for an example.有关示例,请参阅此答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.