socket 设置 keepalive 时间_nginx的keepalive源码分析

http1.1与http1.0最大的区别是什么?

答案是http1.1协议是默认开启keep-alive的,开启后会与服务端保持一定时间的长连接,如图http1.1的请求头:

a0d6e77b575df9f7a7bd00ec4edafd63.png

那什么是keepalive?作用是什么?

keepalive是在TCP中一个可以检测死连接的机制,可以保持tcp长连接不被断开,属于tcp层功能。http1.1协议默认开启keepa-live保持长连接,主要作用是提高对tcp连接的复用率,减少创建连接过程给系统带来的性能损耗。

TCP层怎么做到保持长连接的呢?

先看keepalive的用法:有三个参数,开放给应用层使用:

1. sk->keepalive_probes:探测重试次数,超过次数则close连接;2. sk->keepalive_time  探测的心跳间隔,TCP连接在间隔多少秒之后未进行数据传输,则启动探测报文;3. sk->keepalive_intvl 探测间隔,发送探活报文,未收到回复时,重试的时间间隔;

linux系统对这三个参数有默认配置,查看:

[***@*** ~]$ $  cat/proc/sys/net/ipv4/tcp_keepalive_time300[***@*** ~]$ cat /proc/sys/net/ipv4/tcp_keepalive_intvl75[***@*** ~]$ cat /proc/sys/net/ipv4/tcp_keepalive_probes9

应用层使用示例:

  1. int keepalive = 1; // 开启keepalive属性
  2. int keepidle = 60; // 如该连接在60秒内没有任何数据往来,则进行探测
  3. int keepinterval = 5; // 探测时发包的时间间隔为5 秒
  4. int keepcount = 3; // 探测尝试的次数。如果第1次探测包就收到响应了,则后2次的不再发。并且清零该计数
  5. setsockopt(rs, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive , sizeof(keepalive ));
  6. setsockopt(rs, SOL_TCP, TCP_KEEPIDLE, (void*)&keepidle , sizeof(keepidle ));
  7. setsockopt(rs, SOL_TCP, TCP_KEEPINTVL, (void *)&keepinterval , sizeof(keepinterval ));
  8. setsockopt(rs, SOL_TCP, TCP_KEEPCNT, (void *)&keepcount , sizeof(keepcount ));
应用层这么设置后,会把Linux默认配置覆盖,走手动设置的配置
  • keepcount: 覆盖 tcpkeepaliveprobes
  • keepidle: 覆盖 tcpkeepalivetime
  • keepinterval: 覆盖 tcpkeepalive_intvl对于一个经过三次握手已建立好的tcp连接,如果在keepalive_time时间内双方没有任何的数据包传输,则开启keepalive功能,一端将发送keepalive数据心跳包,若没有收到应答,则每隔keepalive_intvl时间间隔再发送该数据包,发送keepalive_probes次,一直没有收到应答,则发送rst包关闭连接,若收到应答,则将计时器清零。
抓包看看keepalive的探活过程

c2ba02bd9f386ea96d454c64ce26e23d.png

根据抓包继续分析keepalive发送及回复的心跳包内容:先看tcp头的结构为:

typedef struct _TCP_HEADER{
     short m_sSourPort;              // 源端口号16bit short m_sDestPort;              // 目的端口号16bit unsigned int m_uiSequNum;         // req字段 序列号32bit unsigned int m_uiAcknowledgeNum;  //ack字段  确认号32bit short m_sHeaderLenAndFlag;        // 前4位:TCP头长度;中6位:保留;后6位:标志位 short m_sWindowSize;            //win字段  窗口大小16bit short m_sCheckSum;              // 检验和16bit short m_surgentPointer;           // 紧急数据偏移量16bit}__attribute__((packed))TCP_HEADER, *PTCP_HEADER;

看发送的心跳包内容 :

0000 d4 6d 50 f5 02 7f f4 5c    89 cb 35 29 08 00        //mac头 14字节:                                                  45 00  // ip头 20字节 :0010 00 28 10 f4 00 00 40 06    5b dd ac 19 42 76 0a b30020 14 bd           e4 4a 1f 7c 32 7e    7a cb 4c bc 55 08 50 10   // tcp头 20字节0030 10 00 3f 00 00 00//分析tcp头部内容e4 4a //源端口号16bit  10进制为:584421f 7c  //目的端口号16bit 10进制为 : 806032 7e 7a cb // req字段 序列号32bit  10进制为 : 4c bc 55 08 // ack字段  确认号32bit5 // 前4位:TCP头长度 5*4 =20 字节 没问题0 10  /// 中6位:保留;后6位:标志位 10 代表倒数第5位为1, 标识改tcp包为 ACK 确认包 0030 10 00 3f 00 00 00

继续看回复的心跳包内容 :<

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值