linux tcp三路握手详解

转载请附本文链接:https://blog.csdn.net/maxlovezyy/article/details/70338456

可能很多人都觉得自己懂tcp的三路握手,他知道那么三下子如下图。
    这里写图片描述
  但我更想问,你知道这些有个卵用。。。能排查出连接问题吗?可能你觉得用wireshark啊,tcpdump啊抓包能分析,但是你不了解协议栈怎么实现的,是很难做到良好的分析的。本文就告诉你,到底握手的过程中协议栈是怎么一步步处理的。

协议栈处理过程

假设server的半连接和连接队列都是空的,过程如下。

  1. client向server发送【SYN】,状态为【SYN SENT】
  1. server收到client的【SYN】并回复【SYN+ACK】,这时候这个连接进入到server半连接队列,状态为【SYN RECEIVED】
  2. client收到server 【SYN+ACK】,回发【ACK】,client端认为三路握手成功,状态为【ESTABLISHED】
  3. server收到client的【ACK】,这时候这个连接就从server的半连接队列被转入已连接队列,server三路握手成功,状态为【ESTABLISHED】
  4. server调用了accept,这时候连接就从已连接队列移除了。

这里就有几个问题了。比如server端已连接队列满了,server会怎么处理?半连接队列满了呢?又会怎么处理?以下就做一个说明。

  • 如果已连接队列满了,协议栈就会概率性地丢弃收到的SYN包,而对于不决定丢弃留下的SYN包,会回复SYN/ACK,但是之后收到的client回复的ACK会被丢弃,就等于没有收到ACK,进而server会有机制重发SYN/ACK,之后client收到之后就会认为原来我之前发的ACK server没收到啊,继续就会重发ACK。server直至超时都没有完成握手就发送RST,但如果超时时间内已连接队列有空间了并且收到了client的重试的ACK,那么就三路握手成功了。
  • 如果半连接队列满了呢?直接丢弃呗,还想啥。。
  • 三路握手和accept没关系,握手纯属协议栈的事。
  • 理论上只要server足够快地accept,那么backlog队列应该一直是"空"的,只有系统负载比较高的时候,才有必要用一个比较大的backlog值。
  • 只有在服务器和客户端之间的RTT特别大的时候,半连接队列才容易满;否则一般就是被DDOS攻击了。

趣事

我之前做过这样的一个测试:server端listen(fd, 100),client拿着blocking的fd无限地连接,统计connect返回的成功连接的个数。
  这时候client发生了有趣的现象:前100多一点个连接一瞬间完成;之后统计的已连接数就开始慢慢悠悠的一个个增加。这是为什么呢?通过上面的陈述,你完全可以自己解决了。

趣题

server端listen(fd, 100),但是server不调用accept,那么client和server双方视角下,成功连接了多少个?client的视角下成功多少个?

相关数目配置

  • 【连接队列】 个数为listen的backlog参数,但listen的再多也绝对不会超过somaxconn
  • 【半连接队列】个数为tcp_max_syn_backlog

参考链接

http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值