现在的位置: 首页 > 综合 > 正文

如果网络出现异常,TCP连接中断,那么计算机要多久才能够检测出来呢?

2019年08月10日 ⁄ 综合 ⁄ 共 3427字 ⁄ 字号 评论关闭

如果网络出现异常,TCP连接中断,那么计算机要多久才能够检测出来呢?
最佳答案 这个问题得分情况来说:
1、双方只建立了一个连接,然后就再也没有任何数据通信,这完全是可能的。这时,tcp有一个保活定时器,它的作用就是确认对端是否存活,通常它没2个小时发送一个数据包给对方,以查看是否有响应。
2、tcp中断,此时发送端发送数据,但是由于收不到ACK,它会一直尝试,通常的时间间隔为1s, 3s, 6s, 12s ..... 64s,这个间隔被称为"指数退避",到最后,通常在9分钟后放弃(这个值看实现有可能不同)。
3、tcp中断,在这个过程中,路由器检测到主机不可达,当发送数据后会返回一个icmp信息,显示主机不可达,这个通常很快就能检测出来。    TCP在不停发包的情况下仅仅利用TCP的属性是无法发现TCP连接是否正常,希望能够有兄弟姐妹来推翻我的这个论断。
在维护检测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     0x1    
    0x2         00:19:E0:DD:41:18     *        eth1
192.168.10.62    0x1    
    0x2         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  
#include  
#include  
#include  
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 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
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;
}
这样的方法比较简单,不要浪费资源。
用connect的在比较多的连接方面判断起来还是比较吃力的,不过他能跨越路由器。
一般的情况在没有必要检测TCP的连接状态,主要是从TCP的机制考虑的,他的设计初衷就是为了确保间断的连接。不过在一些BT的系统中TCP系统实现的并不完善,需要这样辅助的手段确保对方重新使用新的端口重新连接。

【上篇】
【下篇】

抱歉!评论已关闭.