C语言关于socket中如何判断客户端是不是与服务器保持连接

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言关于socket中如何判断客户端是不是与服务器保持连接相关的知识,希望对你有一定的参考价值。

是一个长期保持的连接,是TCP的,使用了一个死循环不退出套接字以保持连接。
我写的是客户端程序,服务器的程序是不能更改的。
目前的情况是服务器和客户端正常情况下可以通讯。但是担心万一网络断了(网线掉了),或者服务器端主动断开连接,作为客户端的我如何去知道连接已经断开,然后就不继续发数据。
问题1:想过用心跳包,个人理解心跳包的意思是我发数据过去,看有返回数据没,如果达到设置的未返回数据次数,就断定连接出问题了。如果我客户端有心跳包程序,而服务器没有的话,是不是就不会有返回的数据了。
问题2:如果我把WSAGetLastError()这个函数放在send的后面,能否通过返回的值知道连接是否断开。
核心内容还是想知道客户端与服务器是否断开连接,用什么方法都可以。麻烦各位前辈给点建议,感激不尽。

参考技术A 写失败之后获取错误值会告诉你错误原因,是网络断了还是怎么样。
再一个如果远程关闭连接你会收到 EOF。追问

1:远程关闭的意思是正常的服务器关闭还是被动的比如网线掉了这些都会返回一个EOF?

2:获取错误值只是在编写程序的时候可以判断,但是界面作完以后,我只会有1个连接正常的界面显示,如果有错误发生,我怎么认定这个为网络断了或者服务器关了?
希望能用代码+思路的方式实现。谢谢了

追答

    正常的服务器关闭

    不是说“知道连接断开就不发数据吗”? 可以被动一点,就是发数据失败了,看看是不是网络超时,如果是,则认为连接断开,关闭套接字好了。

追问

有代码最好了,伪代码都行,确实头绕晕了。

追答

汗~不写代码十几年~

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

【中文标题】在使用C语言的socket编程中,如何设置服务器接受客户端建立连接的时间限制?【英文标题】:In socket programming using C language, how to set time limit on server for accepting client to establish connection? 【发布时间】:2021-01-23 04:05:10 【问题描述】:

我正在开发一个涉及 1 个客户端和 1 个服务器的应用程序。

我希望服务器只侦听 5 秒钟的连接。如果客户端未尝试建立连接,则服务器应停止侦听并返回错误消息。如果客户端尝试建立连接,那么服务器应该接受连接。

如果客户端没有尝试建立连接,服务器会一直监听。我希望服务器只监听 5 秒,如何实现?

这是服务器端的输出 - 服务器一直在等待客户端:

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); 



【问题讨论】:

【参考方案1】:

您在阻塞模式下使用侦听套接字,因此accept() 将阻塞调用线程,直到客户端连接。要使用超时,请先调用 select()(e)poll() 以等待侦听套接字进入可读状态,指示连接处于挂起状态,然后再调用 accept()

例如:

...

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); 
...

无论哪种方式,请注意这些场景会产生非常小的竞争条件。如果客户端在调用accept() 之前连接然后断开accept() 可能阻塞等待新的挂起连接,或者它可能返回一个在后续 I/O 调用中失败的有效文件描述符。没有任何一种方式可以保证。

要解决竞争条件,您可以:

将监听套接字置于非阻塞模式。如果select() 报告监听套接字有一个挂起的连接,但accept() 无法立即接受,那么您可以采取相应的行动。

在阻塞模式下在侦听套接字上使用accept(),就像您最初一样,但使用alert() 来安排accept() 如果它在5 秒内没有退出则被中断。示例见this answer。

【讨论】:

以上是关于C语言关于socket中如何判断客户端是不是与服务器保持连接的主要内容,如果未能解决你的问题,请参考以下文章

如何判断socket客户端连接断开

c语言如何检测网络是不是连接

C语言 UDP socket 简单客户端 编程,急

c调用 socket 如果客户端连接断开,怎么判断? 还有怎么向多个 连接在一个服务器上的多个客户

Socket服务器端如何检测客户端的连接状态?

c语言中关于socket函数的例子