TCP状态转换图——简述11个状态

1、TCP建立连接需要3次握手

首先,client端会发出一个SYN,server收到之后,会回复ACK,并同时发出一个SYN,client收到后连接就可以建立。三次握手保证了双发通讯正常。

这就和我们打电话一样:

张三:在吗?(向李四发出信息,等待李四响应)

李四:在。   (李四收到信息后,回复张三;到这里只能说明张三的消息,李四可以收到。所以要保证通讯畅通,李四需要向张三发出信息,等待张三回复。) 

张三:收到。 (这里张三回复收到,则意味着李四发出的信息,张三也可以收到。  这样才建立一个可靠的连接)

2、TCP连接断开需要四次挥手

图中的client、service只是为了描述一个连接关闭流程,实际上不管客户端还是服务端都可以主动关闭连接。

为什么需要四次挥手呢?

TCP是全双工通讯,当收到对方发来的FIN包,只意味着对方可以关闭连接了,自己可能还有数据要发送。所以FIN需要单独在发一次。

3、TCP状态转移图

Closed: 是初始状态

Listen:表示服务器的某个socket处于监听状态,可以接受连接

SYN_rcvd:表示收到了SYN报文,这是服务器的一个中间态、很短暂。

SYN_send:客户端发送SYN报文后,会变成这个状态,与SYN_rcvd对应。

Established:表明连接已经建立,这可以说是一个稳定态,使用netstat 可以观察到双方建立的连接。

Close_wait:正常来说,这应该也是一个中间态,它代表着四次挥手中收到对方发来的FIN,回复了ack,在向对方发送FIN之前,就是这个状态。  (很多时候我们会发现程序出问题时出现很多close_wait,这个状态出现就是由于在收到对方关闭连接后,自身未发出FIN包导致。大量的close_wait状态会导致HTTP请求无法响应,你的程序会宕掉,你需要检查一下你的代码了)

LAST_ack:这个状态是被动关闭的一方发送FIN后,等待四次握手中最后一个Ack(也就是主动关闭方发来的ack)之前的状态。

FIN_wait_1:这也是个中间态,基本看不到。当主动关闭方向对方发送FIN报文后,主动方便是FIN_wait_1状态。

FIN_wait_2:接着上面FIN_wait1说的,在主动关闭连接的一方发送FIN报文后,自身成为FIN_wait1,当收到对方的ACK时,变为FIN_wait_2。

TIME_wait:接受到对方的FIN,并回复了ack。此时等待2MSL(MSL为最长报文存活时间,可在操作系统中配置),连接即可关闭。这是一个正常态,存在请求时netstat即可看到。

closing:比较特殊,可能是双发同时关闭连接时会出现的状态。图中可以看到,之后会变为Time_wait,2MSL后连接随之关闭。

4、来看一个HTTP请求的抓包

浮生若梦,忙里偷闲, 使用tcpdump抓包来看看一次HTTP请求TCP连接的建立断开。

一个正常的HTTP请求抓包

tcpdump -i lo -n port 8080 -S

#tcpdump用法自己百度一下

 我们触发一次

15:58:19.333425 IP 127.0.0.1.49455 > 127.0.0.1.8080: Flags [S], seq 4076194383, win 43690, options [mss 65495,sackOK,TS val 1559458260 ecr 0,nop,wscale 7], length 0
15:58:19.333436 IP 127.0.0.1.8080 > 127.0.0.1.49455: Flags [S.], seq 2069165181, ack 4076194384, win 43690, options [mss 65495,sackOK,TS val 1559458260 ecr 1559458260,nop,wscale 7], length 0
15:58:19.333448 IP 127.0.0.1.49455 > 127.0.0.1.8080: Flags [.], ack 2069165182, win 342, options [nop,nop,TS val 1559458260 ecr 1559458260], length 0
15:58:19.333548 IP 127.0.0.1.49455 > 127.0.0.1.8080: Flags [P.], seq 4076194384:4076195143, ack 2069165182, win 342, options [nop,nop,TS val 1559458260 ecr 1559458260], length 759
15:58:19.333562 IP 127.0.0.1.8080 > 127.0.0.1.49455: Flags [.], ack 4076195143, win 354, options [nop,nop,TS val 1559458260 ecr 1559458260], length 0
15:58:19.353547 IP 127.0.0.1.8080 > 127.0.0.1.49455: Flags [P.], seq 2069165182:2069165253, ack 4076195143, win 354, options [nop,nop,TS val 1559458280 ecr 1559458260], length 71
15:58:19.353557 IP 127.0.0.1.49455 > 127.0.0.1.8080: Flags [.], ack 2069165253, win 342, options [nop,nop,TS val 1559458280 ecr 1559458280], length 0
15:58:19.353835 IP 127.0.0.1.8080 > 127.0.0.1.49455: Flags [P.], seq 2069165253:2069165340, ack 4076195143, win 354, options [nop,nop,TS val 1559458281 ecr 1559458280], length 87
15:58:19.353843 IP 127.0.0.1.49455 > 127.0.0.1.8080: Flags [.], ack 2069165340, win 342, options [nop,nop,TS val 1559458281 ecr 1559458281], length 0
15:58:19.354004 IP 127.0.0.1.49455 > 127.0.0.1.8080: Flags [F.], seq 4076195143, ack 2069165340, win 342, options [nop,nop,TS val 1559458281 ecr 1559458281], length 0
15:58:19.354228 IP 127.0.0.1.8080 > 127.0.0.1.49455: Flags [F.], seq 2069165340, ack 4076195144, win 354, options [nop,nop,TS val 1559458281 ecr 1559458281], length 0
15:58:19.354239 IP 127.0.0.1.49455 > 127.0.0.1.8080: Flags [.], ack 2069165341, win 342, options [nop,nop,TS val 1559458281 ecr 1559458281], length 0

TCP Flag包含8个比特位,分别是:CWR,ECE,URG,ACK,PSH,RST,SYN,FIN。

SYN:在建立连接时标记,三次握手中syn就是这个.

ACK:用来告诉对方数据包已收到,返回的数据中会将顺序号+1.

PSH:(push)表示需要将收到的包交给应用层.

FIN:表示自己已经没有数据要发送了,准备关闭连接.

看一下抓包数据,前三个包,就是三次握手建立连接的过程:第一个包Flags[S] 代表客户端发送的SYN,第二个包Flags[S.]代表服务端返回的ack和向客户端发出的SYN,第三个包Flags[.]是客户端回复的ack.至此三次握手完成,连接建立。

中间的包是请求和响应,来看最后三个包.就是四次挥手来关闭连接。

Flags[F.]代表主动关闭的一方没有数据发送了,向对方发送了FIN来关闭连接。倒数第二个包Flags[F.]表示被动一方回复ack,并且发出FIN表示也要关闭连接了(这里FIN与ack一起发可以理解为TCP自身的优化机制),最后一个包F[.]主动关闭一方回复ack,连接关闭。

再来分析一下Flags[P]包中数据的含义:

15:58:19.333548 IP 127.0.0.1.49455 > 127.0.0.1.8080: Flags [P.], seq 4076194384:4076195143, ack 2069165182, win 342, options [nop,nop,TS val 1559458260 ecr 1559458260], length 759

15:58:19.333548: 这个一看就是收到包时间了

127.0.0.1.49455 :是发送方的IP和端口

127.0.0.1.8080 :是服务端的IP和端口

Flags [P.]  :P代表PSH标志位,表明改包需要推送到应用层,至于这里的.可以理解为一个占位符,不考虑。

seq 4076194384:4076195143 : tcp报文的seq号, 4076194384是起始值,4076195143是结束值, 4076195143 -4076194384是发送报文长度。

ack 2069165182 :tcp报文的ack号, ack 2069165182 表明标号2069165181报文已收到。下一个接收的seq号会从2069165182 开始。

win 342 :表示tcp报文发送方作为接收方还可以接受的字节数,大于这个数,可能就处理不了了。

options [nop,nop,TS val 1559458260 ecr 1559458260]:这里nop是 no operation,可以不考虑;TS val 1559458260是报文的时间戳,这个值与系统时间无关,用来做seq值越界重新从0开始计算时,确认包顺序;ecr 1559458260 这个值用来计算RTT

length 759:这个值表示应用层传来数据的大小(不包括TCP header),与上面seq 4076194384:4076195143相减对应。

最后附上一个带完整数据的请求抓包(与上面抓包对应)

tcpdump -i lo -n port 8080 -SAl
15:56:45.608564 IP 127.0.0.1.49075 > 127.0.0.1.8080: Flags [S], seq 3763193645, win 43690, options [mss 65495,sackOK,TS val 1559364535 ecr 0,nop,wscale 7], length 0
..............E..<..@.@.x............-.M.-.........0.........
\...........
15:56:45.608581 IP 127.0.0.1.8080 > 127.0.0.1.49075: Flags [S.], seq 3127397756, ack 3763193646, win 43690, options [mss 65495,sackOK,TS val 1559364535 ecr 1559364535,nop,wscale 7], length 0
..............E..<..@.@.<..........-...hM|.M.......0.........
\...\.......
15:56:45.608595 IP 127.0.0.1.49075 > 127.0.0.1.8080: Flags [.], ack 3127397757, win 342, options [nop,nop,TS val 1559364535 ecr 1559364535], length 0
..............E..4..@.@.x&...........-.M...hM}...V.(.....
\...\...
15:56:45.608705 IP 127.0.0.1.49075 > 127.0.0.1.8080: Flags [P.], seq 3763193646:3763194405, ack 3127397757, win 342, options [nop,nop,TS val 1559364535 ecr 1559364535], length 759
..............E..+..@.@.u............-.M...hM}...V. .....
\...\...GET /rest/ee7d191e/get?page=1&start=0&limit=15 HTTP/1.1
x-real-ip: 172.16.70.33
remote-host: 172.16.70.33
x-forwarded-for: 172.16.70.33
user-agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36
x-requested-with: XMLHttpRequest
accept: */*
referer: http://172.16.70.22/ui
accept-encoding: gzip, deflate
accept-language: zh-CN,zh;q=0.9
cookie: connect.sid=s%3AYbFf2HMeIBrYNw-GY7PH86N0uqRa4Uda.gCS1W0CXVkGAoJg52r7vBWeYvN0615vMSC%2F6aUuro0o
connection: close
user: administrator
sid: YbFf2HMeIBrYNw-GY7PH860uqRa4Uda
ip_address: 172.16.70.33
content-length: 2
Accept-Charset: utf-8
Host: localhost:8080

{}
15:56:45.608715 IP 127.0.0.1.8080 > 127.0.0.1.49075: Flags [.], ack 3763194405, win 354, options [nop,nop,TS val 1559364535 ecr 1559364535], length 0
..............E..4N.@.@............-...hM}.M.%...b.(.....
\...\...
15:56:45.718585 IP 127.0.0.1.8080 > 127.0.0.1.49075: Flags [P.], seq 3127397757:3127397828, ack 3763194405, win 354, options [nop,nop,TS val 1559364645 ecr 1559364535], length 71
..............E..{N.@.@............-...hM}.M.%...b.o.....
\..%\...HTTP/1.1 200 OK
Content-Type: application/json
content-length: 87


15:56:45.718595 IP 127.0.0.1.49075 > 127.0.0.1.8080: Flags [.], ack 3127397828, win 342, options [nop,nop,TS val 1559364645 ecr 1559364645], length 0
..............E..4..@.@.x$...........-.M.%.hM....V.(.....
\..%\..%
15:56:45.718887 IP 127.0.0.1.8080 > 127.0.0.1.49075: Flags [P.], seq 3127397828:3127397915, ack 3763194405, win 354, options [nop,nop,TS val 1559364646 ecr 1559364645], length 87
..............E...N.@.@............-...hM..M.%...b.......
\..&\..%{"result":{"errorDesc":"Successfully","errorCode":0},"list":[],"totalCount":0}
15:56:45.718897 IP 127.0.0.1.49075 > 127.0.0.1.8080: Flags [.], ack 3127397915, win 342, options [nop,nop,TS val 1559364646 ecr 1559364646], length 0
..............E..4..@.@.x#...........-.M.%.hN....V.(.....
\..&\..&
15:56:45.719429 IP 127.0.0.1.49075 > 127.0.0.1.8080: Flags [F.], seq 3763194405, ack 3127397915, win 342, options [nop,nop,TS val 1559364646 ecr 1559364646], length 0
..............E..4..@.@.x"...........-.M.%.hN....V.(.....
\..&\..&
15:56:45.719717 IP 127.0.0.1.8080 > 127.0.0.1.49075: Flags [F.], seq 3127397915, ack 3763194406, win 354, options [nop,nop,TS val 1559364646 ecr 1559364646], length 0
..............E..4N.@.@............-...hN..M.&...b.(.....
\..&\..&
15:56:45.719732 IP 127.0.0.1.49075 > 127.0.0.1.8080: Flags [.], ack 3127397916, win 342, options [nop,nop,TS val 1559364646 ecr 1559364646], length 0
..............E..4..@.@.x!...........-.M.&.hN....V.(.....
\..&\..&

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值