Linux系统下判断TCP连接状态的几种方法 您所在的位置:网站首页 qt客户端判断tcp连接状态 Linux系统下判断TCP连接状态的几种方法

Linux系统下判断TCP连接状态的几种方法

2023-09-25 17:05| 来源: 网络整理| 查看: 265

当客户端与服务端保持长连接时,客户端除了可以使用心跳包来确认连接状态外,还可以使用一下几种方法:

一、使用recv() 函数判断连接状态

使用recv() 函数的MSG_PEEK选项,使用这个选项可以“偷看(peek)”一下接收队列的数据。所谓“偷看”,就是recv()不从接收队列中把数据移除,因此下一次调用recv()函数还会接收到此数据。 当TCP连接处于已建立Established状态时,如果接收队列中有数据,recv()函数返回1;如果接收队列中没有数据但是TCP连接没有断开,recv() 函数返回-1,并且把errno设置为EAGAIN。其余情况下表示TCP连接已经断开。

bool tcp_connection_state(int fd) { char buf[1]; int err; err = recv(fd, buf, sizeof(buf), MSG_PEEK); if (err == 1 || (err == -1 && errno == EAGAIN)) { return true; } return false; }

PS: 注意在获取errno时,也可以使用getsockopt(fd, SOL_SOCKET, SO_ERROR, &status, &status_len)来获取,SO_ERROR选项获得errno的值并且随后置零。

二、使用epoll异步监控连接状态

使用epoll监控socket连接时有两种情况下可以断定此连接已经断开:

当触发可读事件,但是接收字节数为0。这种情况下,FIN数据包在read()调用前,在EPOLLIN唤醒epoll后到达TCP被动关闭方。当EPOLLRDHUP事件唤醒epoll_wait()函数,表示对端主动断开连接。注意当epoll事件返回为EPOLLHUP通常时socket内部错误,而不是连接主动断开。 三、使用getsockopt() 函数的TCP_INFO选项 bool tcp_connection_state(int fd) { struct tcp_info info; int len=sizeof(info); getsockopt(sock, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len); if((info.tcpi_state==TCP_ESTABLISHED)) { return true; } return false; }

在没有使用read()、write()、epoll()时使用

四、使用TCP心跳处理 int keepAlive = 1; // 开启keepalive属性 int keepIdle = 60; // 如该连接在60秒内没有任何数据往来,则进行探测 int keepInterval = 5; // 探测时发包的时间间隔为5 秒 int keepCount = 3; // 探测尝试的次数.如果第1次探测包就收到响应了,则后2次的不再发. setsockopt(rs, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive)); setsockopt(rs, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle)); setsockopt(rs, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval)); setsockopt(rs, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));

设置后,若断开,则在使用该socket读写时立即失败,并返回ETIMEDOUT错误。但是上述方法有个重试次数,tcp连接状态检测检测有滞后性。在linux kernel 2.6.37版本后,支持TCP_USER_TIME_OUT选项,超时后直接判断连接超时。

unsigned int timeout = 1000; //值为数据包被发送后未接收到ACK确认的最大时长,以毫秒 //为单位,例如设置为timeout时,代表如果发送出去的数据包 //在timeout毫秒内未收到ACK确认,则下一次调用send或者recv, //函数会返回-1,errno设置为ETIMEOUT,代表connection timeout。 //使用TCP Keep-alive加上TCP_USER_TIMEOUT机制,就可以完美解 //决通信对端异常断网、掉电的情况下,连接被长期挂起的问题了。 setsockopt(socket_fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout, sizeof(timeout)); 五、使用七层心跳处理

有时服务端程序停止服务,但是内核还维护着TCP连接。在这种情况下,使用7层的心跳处理是有效的,

参考 怎样实时判断socket连接状态?How do I use EPOLLHUP

大家对此问题有什么想法,欢迎讨论。加油,打工人!



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有