TCP检测连接非正常中断
2010-07-25 14:39
260 查看
http://blog.201314.info/tag/so_sndtimeo
在维护检测TCP的正常连接方面 SOL_SOCKET类提供了SO_KEEPALIVE 保持连接 int
SO_RCVTIMEO 接收超时 struct timeval
SO_SNDTIMEO 发送超时 struct timeval
SOL_TCP类提供了
TCP_KEEPIDLE /*开始首次KeepAlive探测前的TCP空闭时间 */
TCP_KEEPINTVL /* 两次KeepAlive探测间的时间间隔 */
TCP_KEEPCNT /* 判定断开前的KeepAlive探测次数 */
上面的几个SOCKET属性是用来检测连接情况和传送接受属性的,但是在不停发包的情况下是不能使用的,不是说是TCP的缺陷,而是他设计的初衷就是为了维护短暂的中断的连接。 在已经连接上以后,不间断的发包会使得TCP的连接状态维持在ESTABLISHED上。
你可以在你的代码里面使用alarm函数,每隔几秒种发包,中间拔开网线然后用 netstat -t 来查看TCP的连接状况:
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 192.168.10.22:5300 192.168.10.62:3117 ESTABLISHED
同样即使你发现网线拨开以后机子发送了几个ARP的查询包,很不幸的告诉你,即使没有收到ARP的查询回复包。在ARP Entry里面该mac地址然后不会被老化。
cat /proc/net/arp
IP address HW type Flags HW address Mask Device
192.168.10.1 0×1 0×2 00:19:E0:DD:41:18 * eth1
192.168.10.62 0×1 0×2 00:16:76:CC:1D:4E * eth1
如果你不想使用《UNIX 网络编程第1卷》上介绍的心博函数(因为需要客户端也要支持),你可以使用两个方法。这两种方法都属于非常规做法,希望各位在使用之前务必清楚TCP连接中会发生什么情况,返回什么样的错误号。
第一种:
Linux平台下,可以通过在connect之前设置SO_SNDTIMO来达到控制连接超时的目的。简单的写了份测试代码:
#include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <errno.h> int main(int argc, char *argv[]) { int fd; struct sockaddr_in addr; struct timeval timeo = {3, 0}; socklen_t len = sizeof(timeo); fd = socket(AF_INET, SOCK_STREAM, 0); if (argc == 4) timeo.tv_sec = atoi(argv[3]); setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeo, len); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(argv[1]); addr.sin_port = htons(atoi(argv[2])); if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { if (errno == EINPROGRESS) { fprintf(stderr, "timeout/n"); return -1; } perror("connect"); return 0; } printf("connected/n"); return 0; } |
第二种:
删除Arp地址,通过检测是否能够再次获得对端mac地址来判断对方是否存活。缺点是不能跨越路由器,同样不能检测可以保证测试到对端的程序是否正常工作:
#include <sys/ioctl.h> #include <sys/socket.h> #include <net/if.h> #include <netinet/if_ether.h> int get_arp(unsigned int ip) { int sd; struct arpreq arpreq; struct sockaddr_in *sin; struct in_addr ina; unsigned char *hw_addr; int rc; sd = socket(AF_INET, SOCK_DGRAM, 0); if (sd < 0) { perror(“socket() error/n”); exit(1); } /* Try to find an entry in arp cache for the ip address specified */ printf(“Find arp entry for IP : %s/n”, ip); memset(&arpreq, 0, sizeof(struct arpreq)); sin = (struct sockaddr_in *) &arpreq.arp_pa; memset(sin, 0, sizeof(struct sockaddr_in)); sin->sin_family = AF_INET; ina.s_addr = ip;//inet_addr(ip); memcpy(&sin->sin_addr, (char *)&ina, sizeof(struct in_addr)); strcpy(arpreq.arp_dev, “eth1″); rc = ioctl(sd, SIOCGARP, &arpreq); return rc; } int del_arp(unsigned int ip) { int sd; struct arpreq arpreq; struct sockaddr_in *sin; struct in_addr ina; unsigned char *hw_addr; int rc; sd = socket(AF_INET, SOCK_DGRAM, 0); if (sd < 0) { perror(“socket() error/n”); exit(1); } /* Try to find an entry in arp cache for the ip address specified */ printf(“Find arp entry for IP : %s/n”, ip); memset(&arpreq, 0, sizeof(struct arpreq)); sin = (struct sockaddr_in *) &arpreq.arp_pa; memset(sin, 0, sizeof(struct sockaddr_in)); sin->sin_family = AF_INET; ina.s_addr = ip;//inet_addr(ip); memcpy(&sin->sin_addr, (char *)&ina, sizeof(struct in_addr)); strcpy(arpreq.arp_dev, “eth1″); rc = ioctl(sd, SIOCDARP, &arpreq); return rc; } |
一般的情况在没有必要检测TCP的连接状态,主要是从TCP的机制考虑的,他的设计初衷就是为了保证间断的连接。但是在一些BT的系统中TCP系统实现的并不完善,需要这样辅助的手段保证对方重新使用新的端口重新连接。
相关文章推荐
- 如果网络出现异常,TCP连接中断,那么计算机要多久才能够检测出来呢?
- 长期使人困惑的问题:TCP连接中断的实时检测
- [原创]Coding4Fun检测你的网络,用C#获取本机TCP、UDP状态及连接(一)
- tcp连接检测-keep-alive
- tcp连接检测Keep-alive
- Android系统下检测Wifi连接互联网是否正常的代码
- (转)TCP连接异常断开检测
- TCP连接断线后,如何检测?
- 检测网络是否连接正常
- TCP连接异常断开检测
- 检测网络连接是否正常的方法
- C# TcpClient 连接状态检测
- 检测网络是否连接正常
- 第18章(一)TCP连接建立和终止的正常情况
- 怎样及时检测出非正常断开的TCP连接
- TCP连接异常断开检测
- tcp连接检测-keep-alive
- tcp连接检测及重连
- 检测TCP非正常断开连接 SO_KEEPALIVE 使用缺陷分析
- 怎样及时检测出非正常断开的TCP连接(转)