zoukankan      html  css  js  c++  java
  • TCP的保活定时器 转

    http://blog.csdn.net/zhangskd/article/details/44177475

    TCP的Keepalive,目的在于看看对方有没有发生异常,如果有异常就及时关闭连接。

    当传输双方不主动关闭连接时,就算双方没有交换任何数据,连接也是一直有效的。

    如果这个时候对端、中间网络出现异常而导致连接不可用,本端如何得知这一信息呢?

    答案就是保活定时器。它每隔一段时间会超时,超时后会检查连接是否空闲太久了,如果空闲的时间超过

    了设置时间,就会发送探测报文。然后通过对端是否响应、响应是否符合预期,来判断对端是否正常,

    如果不正常,就主动关闭连接。

    当服务器发送探测报文时,客户端可能处于4种不同的情况:仍然正常运行、已经崩溃、已经崩溃并重启了、

    由于中间链路问题不可达。在不同的情况下,服务器会得到不一样的反馈。

    (1) 客户主机依然正常运行,并且从服务器端可达

    客户端的TCP响应正常,从而服务器端知道对方是正常的。保活定时器会在两小时以后继续触发。

    (2) 客户主机已经崩溃,并且关闭或者正在重新启动

    客户端的TCP没有响应,服务器没有收到对探测包的响应,此后每隔75s发送探测报文,一共发送9次。

    socket函数会返回-1,errno设置为ETIMEDOUT,表示连接超时。

    (3) 客户主机已经崩溃,并且重新启动了

    客户端的TCP发送RST,服务器端收到后关闭此连接。

    socket函数会返回-1,errno设置为ECONNRESET,表示连接被对端复位了。

    (4) 客户主机依然正常运行,但是从服务器不可达

    双方的反应和第二种是一样的,因为服务器不能区分对端异常与中间链路异常。

    socket函数会返回-1,errno设置为EHOSTUNREACH,表示对端不可达。

    内核默认并不使用TCP Keepalive功能,除非用户设置了SO_KEEPALIVE选项。

    有两种方式可以自行调整保活定时器的参数:一种是修改TCP参数,一种是使用TCP层选项。

    (1) TCP参数

    tcp_keepalive_time

    最后一次数据交换到TCP发送第一个保活探测报文的时间,即允许连接空闲的时间,默认为7200s。

    tcp_keepalive_intvl

    保活探测报文的重传时间,默认为75s。

    tcp_keepalive_probes

    保活探测报文的发送次数,默认为9次。

    Q:一次完整的保活探测需要花费多长时间?

    A:tcp_keepalive_time + tcp_keepalive_intvl * tcp_keepalive_probes,默认值为7875s。

    如果觉得两个多小时太长了,可以自行调整上述参数。

    (2) TCP层选项

    TCP_KEEPIDLE:含义同tcp_keepalive_time。

    TCP_KEEPINTVL:含义同tcp_keepalive_intvl。

    TCP_KEEPCNT:含义同tcp_keepalive_probes。

    Q:既然有了TCP参数可供调整,为什么还增加了上述的TCP层选项?

    A:TCP参数是面向本机的所有TCP连接,一旦调整了,对所有的连接都有效。

    而TCP层选项是面向一条连接的,一旦调整了,只对本条连接有效。

    激活

    在连接建立后,可以通过设置SO_KEEPALIVE选项,来激活保活定时器。

    int keepalive = 1;

    setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive));

    可以使用TCP层选项来动态调整保活定时器的参数。

    int keepidle = 600;

    int keepintvl = 10;

    int keepcnt = 6;

    setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle));

    setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &keepintvl, sizeof(keepintvl));

    setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &keepcnt, sizeof(keepcnt));

  • 相关阅读:
    4.7字符串
    4.5 基本类型和运算符
    4.4 变量
    4.6 字符串
    hp
    openstack newton linuxbridge 改成 ovs
    理解裸机部署过程ironic
    csredis base usage
    redisclient can not connect
    Linux Install redis
  • 原文地址:https://www.cnblogs.com/zendu/p/5795403.html
Copyright © 2011-2022 走看看