zoukankan      html  css  js  c++  java
  • UNIX网络编程——套接字选项(心跳检测、绑定地址复用)(转)

    /* 设置套接字选项周期性消息检测连通性 心跳包、 心博。主要用于长连接。
     * 参数:套接字, 1或0开启, 首次间隔时间, 两次间隔时间, 断开次数
     */
    void setKeepAlive( int iSockfd , int iSockAttrOn, socklen_t iIdleTime , socklen_t iInterval , socklen_t iCount ){
        setsockopt( iSockfd , SOL_SOCKET , SO_KEEPALIVE , (const char*)&iSockAttrOn , sizeof(iSockAttrOn) );
        setsockopt( iSockfd , SOL_TCP , TCP_KEEPIDLE , (const char*)&iIdleTime , sizeof(iIdleTime) );
        setsockopt( iSockfd , SOL_TCP , TCP_KEEPINTVL , (const char*)&iInterval,sizeof(iInterval) );
        setsockopt( iSockfd , SOL_TCP , TCP_KEEPCNT , (const char*)&iCount,sizeof(iCount) );
    }
    /* 绑定地址复用. 主要用于TCP Server端 */
    setsockopt(iSockfd, SOL_SOCKET, SO_REUSEADDR, &iSockAttrOn,sizeof(iSockAttrOn) );


     SO_KEEPALIVE 保持连接检测对方主机是否崩溃,避免(服务器)永远阻塞于TCP连接的输入。设置该选项后,如果2小时内在此套接口的任一方向都没有数据交换(即服务器没有发送数据或者接收数据,TCP就自动给对方发一个保持存活探测分节(keepalive probe)。这是一个对方必须响应的TCP分节.它会导致以下三种情况:

    • 对方接收一切正常:以期望的ACK响应。
    • 2小时后,TCP将发出另一个探测分节。对方已崩溃且已重新启动:以RST响应。套接口的待处理错误被置为ECONNRESET(recv返回0,errno为ECONNRESET),套接字本身则被关闭。
    • 对方无任何响应:源自berkeley的TCP发送另外8个探测分节,相隔75秒一个,试图得到一个响应。在发出第一个探测分节11分钟15秒(9*75s)后若仍无响应就放弃。套接口的待处理错误被置为ETIMEOUT,套接口本身则被关闭。如ICMP错误是“host unreachable(主机不可达)”,说明对方主机并没有崩溃,但是不可达,这种情况下待处理错误被置为EHOSTUNREACH。

            如果我们不能接受如此之长的等待时间,从TCP-Keepalive-HOWTO上可以知道一共有两种方式可以设置。

     

    • 修改内核关于网络方面的配置参数
    echo 30 > /proc/sys/net/ipv4/tcp_keepalive_time
    echo 10 > /proc/sys/net/ipv4/tcp_keepalive_intvl
    echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes

    SOL_TCP字段的TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT三个选项

    1) The tcp_keepidle parameter specifies the interval of inactivity that causes TCP to generate a KEEPALIVE transmission for an application that requests them. tcp_keepidle defaults to 14400 (two hours).

    /*开始首次KeepAlive探测前的TCP空闭时间 */

     

    2) The tcp_keepintvl parameter specifies the interval between the nine retries that are attempted if a KEEPALIVE transmission is not acknowledged. tcp_keepintvl defaults to 150 (75 seconds).
        /* 两次KeepAlive探测间的时间间隔  */


        3) The tcp_keepcnt option specifies the maximum number of keepalive probes to be sent. The value of TCP_KEEPCNT is an integer value between 1 and n, where n is the value of the systemwide tcp_keepcnt parameter.

    /* 判定断开前的KeepAlive探测次数

     

    int                 keepIdle = 1000;
    int                 keepInterval = 10;
    int                 keepCount = 10;
    Setsockopt(listenfd, SOL_TCP, TCP_KEEPIDLE, (void *)&keepIdle, sizeof(keepIdle));
    Setsockopt(listenfd, SOL_TCP,TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));
    Setsockopt(listenfd,SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));

     

      Remember that keepalive is not program?related, but socket?related, so if you have multiple sockets, you can handle keepalive for each of them separately.

    我们需要注意的TCP-Keepalive-HOWTO上这段话:

    Remember that keepalive is not program−related, but socket−related, so if you have multiple sockets, you can handle keepalive for each of them separately.

    这些属性是sockt继承的,即listen的套接字设置该属性后,后面建立连接后的accept 套接字同样继承该属性(心跳属性)。

        如果心搏函数要维护客户端的存活,即服务器必须每隔一段时间必须向客户段发送一定的数据,那么使用SO_KEEPALIVE是有很大的不足的。因为SO_KEEPALIVE选项指"此套接口的任一方向都没有数据交换"。在Linux 2.6系列上,上面话的理解是只要打开SO_KEEPALIVE选项的套接口端检测到数据发送或者数据接收就认为是数据交换。即在非正常断开的情况下(服务器没有收到“FIN”或者“RST”包),上层程序还是可以正常发送包到缓冲区的,而客户端已经异常断开,导致TCP会自动进行重传,重传包的优先级高于keepalive包,那就意味着keepalive总是不能发送出去,这时我们并不知道该连接已经出错而中断,在较长时间的重传失败之后,再发keepalive之后我们才知道客户端异常退出。

    http://blog.csdn.net/ctthuangcheng/article/details/9450087

  • 相关阅读:
    组件基础
    css 手稿
    HTML手稿
    Vmstat命令监控Linux资源并将数据通过图形化方式显示
    JAVA---类和对象
    JAVA---Graphics2D类
    JAVA---数组
    JAVA---图形处理
    JAVA----日历源代码
    SQL常用语句大全
  • 原文地址:https://www.cnblogs.com/wainiwann/p/4024544.html
Copyright © 2011-2022 走看看