简体   繁体   English

C语言socket编程中,如何设置服务器端接受客户端建立连接的时间限制?

[英]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.

相关问题 我们如何通过套接字编程(Python)与不同网络上的服务器和客户端建立服务器和客户端之间的连接? - How could we establish connection between server and client through socket programming(Python) with server and client on different networks? 在Visual C ++中接受来自客户端(套接字编程)的连接的问题 - Problem in accepting connection from client (socket programming) in Visual C++ 如何在Play 2服务器和C#应用程序之间建立套接字连接? - How to establish a socket connection between a Play 2 server and a C# application? 在新客户端连接到服务器后尝试 fork() [Socket Programming C] - Trying to fork() after new client connection to server [Socket Programming C] C-套接字编程客户端服务器-主机名上的连接 - C - socket programming client server - connection on host name 如何在meteor中的服务器端套接字和html/javascript中的客户端套接字之间建立连接 - How to establish connection between server side socket in meteor and client side socket in html/javascript 无法在C中建立客户端和服务器之间的连接 - Unable to establish connection between client and server in C 如何在Python客户端服务器套接字编程之间实现SSL连接 - How to implement SSL connection between Python client server socket programming 服务器/客户端使用套接字编程 - Server/Client using socket programming 基于UNIX套接字的客户端程序中的C ++ connect()无法建立与服务器的连接 - C++ connect() in UNIX-socket based client program does not establish a connection to the server
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM