最近项目需要做单机100万长连接与高并发的服务器,我们开发完服务器以后,通过自己搭的高速压测框架压测服务端的时候,发生了奇怪的现象,就是服务端莫名其妙的少接收了连接,造成了数据包的丢失,通过网上查资料,和自己的实践,下面是我做实验,抓包分析的过程如下:

总共5个连接

其中全连接队列somaxconn参数为1表示监听队列的总长度(实际可以完成somaxconn+1个连接的建立)

半连接队列tcp_max_syn_backlog为1(实际可以将tcp_max_syn_backlog+1个syn分节放入其中)

当全连接队列已满且半连接队列未满的情况下:

当客户端发起一个syn分节时,服务端不会丢弃该syn分节,而是直接响应ack和syn,这时客户端响应ack,并成为established状态,而服务端收到ack响应后,试图将该syn分节从半连接队列中移除,并加入全链接队列,然后由于全连接队列已经满了,这时,在默认情况下,服务端啥也不做,而且不会将该连接由SYN_RECV变成ESTABLISHED,服务端仅仅只是创建一个定时器,以固定间隔重传syn和ack到服务端,直到到达系统默认的synack重传阖值,然后服务端将处于半连接队列里面的syn分节丢弃,此时服务端只剩2个连接。这个时候客户端一侧的连接仍然有5个established

当全连接已满且半连接队列也满的情况下:

当客户端发起一个syn分节时,服务端发现半连接队列已经满了,同时该syn分节尚未重传过,服务端直接丢弃该syn分节,然后客户端过了4秒重传syn分节,这个时候服务端发现半连接队列已满同时,该syn分节已经重传过了,服务端收下了该syn分节,并响应客户端syn+ack,客户端收到syn+ack后,响应ack。客户端三次握手已经完成,而服务端收到ack之后,发现全连接队列是满的,这个时候不会将该连接从SYN_RECV转换成ESTABLISHED,服务端创建定时器,定时重传syn+ack, 直到到达系统默认的synack重传阖值,然后服务端将处于半连接队列里面的syn分节丢弃

具体如下

使用tcpdump -i eth0 -l -nn -S  port 8000 -c 40 -w out.txt

如下所示,测试环境在Linux 2.6.18-164.el5

全连接队列  cat /proc/sys/net/core/somaxconn  1

半连接队列  cat /proc/sys/net/ipv4/tcp_max_syn_backlog  1

监听端口 8000

以客户端建立5条连接为例

1.临时端口号为53991的客户端连接向监听端口为8000的服务端连接发起syn分节,客户端状态变为SYN_SEND状态

服务端收到来自客户端的syn分节后,这个时候由于半连接队列未满,直接将syn分节放入半连接队列,同时向客户端发送了一个ack+syn分节,此时服务端进入SYN_RECV状态

客户端收到服务端发送的syn分节之后,向服务端回传了ack确认分节,客户端进入ESTABLISHED状态

服务端收到来自客户端的ack确认之后,就试图把syn分节从半连接队列中移除,并加入到全连接队列,由于全连接队列未满,此时该syn分节成功转入全连接队列,服务端的状

态从SYN_RECV转换成了ESTABLISHED状态

2.临时端口号为53992的客户端连接和临时端口号为53991的连接同样顺利的完成3次握手

根据以上连接基本可以得出一个结论,能建立起全连接队列长度+1个长连接

3.临时端口号为53993的客户端连接向监听端口为8000的服务端连接发起syn分节,客户端状态变为SYN_SEND状态

服务端收到来自客户端的syn分节后,这个时候由于半连接队列未满,直接将syn分节放入半连接队列,同时向客户端发送一个ack+syn分节,此时服务端进入SYN_RECV状态

客户端收到服务端发送的syn分节之后,向服务端回传了ack确认分节,客户端进入ESTABLISHED状态

服务端收到来自客户端的ack确认之后,就试图把syn分节从半连接队列中移除,并加入全连接队列,由于全连接队列已经满了,此时该syn分节无法转入全连接队列,也就不会

从SYN_RECV转换为ESTABLISHED状态系统默认会把该syn标记为acked模式,并建立定时器,定时从服务端重传syn+ack分节,客户端此时已经处于ESTABLISHED状态,

不过在收到服务端发送的syn+ack分节后,仍然响应服务端ack。服务端继续上面的过程,直到到达synack(cat /proc/sys/net/ipv4/tcp_synack_retries )重传的阖值,然后抛弃

该syn分节

4.临时端口号为53994的客户端连接和临时端口号为53993的连接同样的过程

根据以上连接基本可以得出一个结论,半连接队列能容下半连接队列长度+1个syn分节

5.临时端口号为53995的客户端连接向监听端口为8000的服务端连接发起syn分节,客户端状态变为SYN_SEND状态

服务端收到来自客户端的syn分节后,这个时候半连接队列已经满了,服务端发现该syn分节尚未重传过,默认直接丢弃该syn分节,客户端在超时时间内并未收到来自服务端的

ack响应,大约过了3秒,客户端重传了syn分节,这个时候服务端收到syn分节之后,发现该分节已经收到过,这次服务端收下了syn分节,并向客户端发送syn+ack。客户端

收到来自服务端的ack+syn之后,向服务端发送ack,客户端进入ESTABLISHED状态,服务端收到来自客户端的ack之后,试图把syn分节从半连接队列中移除,并添加到全连

接队列,由于半连接队列已满,加入全连接队列失败,和临时端口号53993以及53994的行为是一样的

1.

20:25:57.637476 IP 192.168.172.128.53991 > 192.168.172.128.8000: S 3828162025:3828162025(0) win 32792 <mss 16396,sackOK,timestamp 250818 0,nop,wscale 6>

20:25:57.637483 IP 192.168.172.128.8000 > 192.168.172.128.53991: S 3826007261:3826007261(0) ack 3828162026 win 32768 <mss 16396,sackOK,timestamp 250818 250818,nop,wscale 6>

20:25:57.637486 IP 192.168.172.128.53991 > 192.168.172.128.8000: . ack 3826007262 win 513 <nop,nop,timestamp 250818 250818>

2.

20:25:58.638894 IP 192.168.172.128.53992> 192.168.172.128.8000: S 3822825008:3822825008(0) win 32792 <mss 16396,sackOK,timestamp 251820 0,nop,wscale 6>

20:25:58.638984 IP 192.168.172.128.8000 > 192.168.172.128.53992: S 3829073969:3829073969(0) ack 3822825009 win 32768 <mss 16396,sackOK,timestamp 251820 251820,nop,wscale 6>

20:25:58.638995 IP 192.168.172.128.53992 > 192.168.172.128.8000: . ack 3829073970 win 513 <nop,nop,timestamp 251820 251820>

3.

20:25:59.640701 IP 192.168.172.128.53993> 192.168.172.128.8000: S 3828629154:3828629154(0) win 32792 <mss 16396,sackOK,timestamp 252821 0,nop,wscale 6>

20:25:59.640713 IP 192.168.172.128.8000 > 192.168.172.128.53993: S 3833556338:3833556338(0) ack 3828629155 win 32768 <mss 16396,sackOK,timestamp 252821 252821,nop,wscale 6>

20:25:59.640719 IP 192.168.172.128.53993 > 192.168.172.128.8000: . ack 3833556339 win 513 <nop,nop,timestamp 252821 252821>

4.

20:26:00.642260 IP 192.168.172.128.53994 > 192.168.172.128.8000: S 3820886884:3820886884(0) win 32792 <mss 16396,sackOK,timestamp 253823 0,nop,wscale 6>

20:26:00.642345 IP 192.168.172.128.8000> 192.168.172.128.53994: S 3831669364:3831669364(0) ack 3820886885 win 32768 <mss 16396,sackOK,timestamp 253823 253823,nop,wscale 6>

20:26:00.642356 IP 192.168.172.128.53994> 192.168.172.128.8000: . ack 3831669365 win 513 <nop,nop,timestamp 253823 253823>

5.

20:26:01.645291 IP 192.168.172.128.53995> 192.168.172.128.8000: S 3824454212:3824454212(0) win 32792 <mss 16396,sackOK,timestamp 254826 0,nop,wscale 6>

3.

20:26:03.040319 IP 192.168.172.128.8000 > 192.168.172.128.53993: S 3833556338:3833556338(0) ack 3828629155 win 32768 <mss 16396,sackOK,timestamp 256221 252821,nop,wscale 6>

20:26:03.040332 IP 192.168.172.128.53993 > 192.168.172.128.8000: . ack 3833556339 win 513 <nop,nop,timestamp 256221 256221,nop,nop,sack 1 {3833556338:3833556339}>

4.

20:26:03.842281 IP 192.168.172.128.8000 > 192.168.172.128.53994: S 3831669364:3831669364(0) ack 3820886885 win 32768 <mss 16396,sackOK,timestamp 257023 253823,nop,wscale 6>

20:26:03.842295 IP 192.168.172.128.53994 > 192.168.172.128.8000: . ack 3831669365 win 513 <nop,nop,timestamp 257023 257023,nop,nop,sack 1 {3831669364:3831669365}>

5.

20:26:04.645946 IP 192.168.172.128.53995 > 192.168.172.128.8000: S 3824454212:3824454212(0) win 32792 <mss 16396,sackOK,timestamp 257826 0,nop,wscale 6>

20:26:04.645962 IP 192.168.172.128.8000 > 192.168.172.128.53995: S 3832652478:3832652478(0) ack 3824454213 win 32768 <mss 16396,sackOK,timestamp 257826 257826,nop,wscale 6>

20:26:04.645971 IP 192.168.172.128.53995 > 192.168.172.128.8000: . ack 3832652479 win 513 <nop,nop,timestamp 257826 257826>

20:26:08.846521 IP 192.168.172.128.8000 > 192.168.172.128.53995: S 3832652478:3832652478(0) ack 3824454213 win 32768 <mss 16396,sackOK,timestamp 262026 257826,nop,wscale 6>

20:26:08.846534 IP 192.168.172.128.53995 > 192.168.172.128.8000: . ack 3832652479 win 513 <nop,nop,timestamp 262026 262026,nop,nop,sack 1 {3832652478:3832652479}>

3.

20:26:09.246438 IP 192.168.172.128.8000 > 192.168.172.128.53993: S 3833556338:3833556338(0) ack 3828629155 win 32768 <mss 16396,sackOK,timestamp 262426 256221,nop,wscale 6>

20:26:09.246452 IP 192.168.172.128.53993 > 192.168.172.128.8000: . ack 3833556339 win 513 <nop,nop,timestamp 262426 262426,nop,nop,sack 1 {3833556338:3833556339}>

4.

20:26:09.853232 IP 192.168.172.128.8000 > 192.168.172.128.53994: S 3831669364:3831669364(0) ack 3820886885 win 32768 <mss 16396,sackOK,timestamp 263026 257023,nop,wscale 6>

20:26:09.853246 IP 192.168.172.128.53994 > 192.168.172.128.8000: . ack 3831669365 win 513 <nop,nop,timestamp 263026 263026,nop,nop,sack 1 {3831669364:3831669365}>

5.

20:26:15.055318 IP 192.168.172.128.8000 > 192.168.172.128.53995: S 3832652478:3832652478(0) ack 3824454213 win 32768 <mss 16396,sackOK,timestamp 268228 262026,nop,wscale 6>

20:26:15.055335 IP 192.168.172.128.53995 > 192.168.172.128.8000: . ack 3832652479 win 513 <nop,nop,timestamp 268228 268228,nop,nop,sack 1 {3832652478:3832652479}>

3.

20:26:21.260288 IP 192.168.172.128.8000 > 192.168.172.128.53993: S 3833556338:3833556338(0) ack 3828629155 win 32768 <mss 16396,sackOK,timestamp 274430 262426,nop,wscale 6>

20:26:21.260308 IP 192.168.172.128.53993 > 192.168.172.128.8000: . ack 3833556339 win 513 <nop,nop,timestamp 274430 274430,nop,nop,sack 1 {3833556338:3833556339}>

TCP全连接队列和半连接队列已满之后的连接建立过程抓包分析[转]的更多相关文章

  1. 五分钟带你读懂 TCP全连接队列(图文并茂)

    爱生活,爱编码,微信搜一搜[架构技术专栏]关注这个喜欢分享的地方. 本文 架构技术专栏 已收录,有各种视频.资料以及技术文章. 一.问题 今天有个小伙伴跑过来告诉我有个奇怪的问题需要协助下,问题确实也 ...

  2. 性能分析之TCP全连接队列占满问题分析及优化过程(转载)

    前言 在对一个挡板系统进行测试时,遇到一个由于TCP全连接队列被占满而影响系统性能的问题,这里记录下如何进行分析及解决的. 理解下TCP建立连接过程与队列 从图中明显可以看出建立 TCP 连接的时候, ...

  3. Python写安全小工具-TCP全连接端口扫描器

    通过端口扫描我们可以知道目标主机都开放了哪些服务,下面通过TCP connect来实现一个TCP全连接端口扫描器. 一个简单的端口扫描器 #!/usr/bin/python3 # -*- coding ...

  4. FTP协议的粗浅学习--利用wireshark抓包分析相关tcp连接

    一.为什么写这个 昨天遇到个ftp相关的问题,关于ftp匿名访问的.花费了大量的脑细胞后,终于搞定了服务端的配置,现在客户端可以像下图一样,直接在浏览器输入url,即可直接访问. 期间不会弹出输入用户 ...

  5. linux下使用tcpdump抓包分析tcp的三次握手

    首先贴上tcp 三次握手的原理图服务器开启ftp服务并执行tcpdump抓包服务器:192.168.3.14 ftp服务客户端:192.168.3.100 服务器执行以下命令,客户端访问服务器ftp: ...

  6. 抓包分析TCP的三次握手和四次握手

    问题描写叙述: 在上一篇<怎样对Android设备进行抓包>中提到了,server的开发者须要我bug重现然后提供抓包给他们分析.所以抓好包自己也试着分析了一下.发现里面全是一些TCP协议 ...

  7. 网络协议抓包分析——TCP传输控制协议(连接建立、释放)

    前言 TCP协议为数据提供可靠的端到端的传输,处理数据的顺序和错误恢复,保证数据能够到达其应到达的地方.TCP协议是面向连接的,在两台主机使用TCP协议进行通信之前,会先建立一个TCP连接(三次握手) ...

  8. Wireshark抓包分析TCP 3次握手、4次挥手过程

    Wireshark简介 更多有关Wireshark的教程.软件下载等,请见:http://www.52im.net/thread-259-1-1.html,本文只作简要介绍. 1Wireshark 是 ...

  9. TCP\IP协议实践:wireshark抓包分析之链路层与网络层

    目录 TCP\IP协议实践:wireshark抓包分析之链路层与网络层 从ping开始 链路层之以太网封装 ip首部 开启ping程序,开始抓包 由一个ping的结果引出来的两个协议ARP ICMP ...

随机推荐

  1. 提取微信小程序“头脑王者”业务逻辑

    产品经理今天让我整理微信小程序"头脑王者"的产品逻辑,花了一天时间在XMind写了写,整理后的内容如图,分享给大家希望大家可以多多点评,互相学习,不知道应该写什么,重要的内容都在图 ...

  2. RHM-M10汽车吊力矩限制器/载荷指示器

    一 产品特点 1.     采用7.0寸工业65K色TFT LCD真彩屏,亮度250nit,分辨率800×480: 2.     传感器采用进口机芯,过载能力强: 3.     采用油压取力和大臂弯曲 ...

  3. CCNA笔记(3)

    网络类型 1,局域网 在一定范围的网络连接,只允许内部人员使用 2城域网 一个城市的网络连接在一起 3.广域网 一个省或者一个市的网络 所有的局域网加上广域网就是互联网

  4. JavaScript判断对象是否含有某个属性

    两种方式,但稍有区别 1,in 运算符 1 2 3 var obj = {name:'jack'}; alert('name' in obj); // --> true alert('toStr ...

  5. js分享功能

    引用JiaThis的分享功能: 直接在想要放置分享功能的地方加上如下代码即可: <!-- JiaThis Button BEGIN --> <div class="jiat ...

  6. 排序算法的实现(C/C++实现)

    存档: #include <iostream> #include <stdlib.h> #include <sort.h> #define maxsize 20 u ...

  7. POJ 1655 Balancing Act【树的重心】

    Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14251   Accepted: 6027 De ...

  8. python列表三

    >>> list1 = [123]>>> list2 =[234]>>> list1 > list2False>>> li ...

  9. Oracle_字段数据类型

    Oracle_字段数据类型 数据库表字段的数据类型 字符数据类型 CHAR:存储固定长度的字符串 VARCHAR2 :存储可变长度的字符串 数值数据类型 NUMBER:存储整数和浮点数,格式为NUMB ...

  10. drawpoly()函数的用法

    画多边形的函数drawpoly() 用当前绘图色.线型及线宽,画一个给定若干点所定义的多边形.第一个参数,是多边形的顶点数第二个参数,是该数组中是多边形所有顶点(x,y)坐标值,即一系列整数对