详解TCP建立连接、传输数据、断开连接全过程

本文通过wrieshark抓取TCP包,来对TCP进行细致的解析,从实践中了解TCP各个过程。

首先介绍下TCP的6种标志位,wriehark会根据这些标志位,在抓取的包中进行标记,方便我们查看:

SYN(synchronous建立联机) 

ACK(acknowledgement 确认) 

PSH(push传送) 

FIN(finish结束) 

RST(reset重置) 

URG(urgent紧急)

Sequence number(顺序号码) 

Acknowledge number(确认号码)

1、三次握手建立连接:

如上图所示,第一次握手,客户端(端口号为44882)向服务器(端口号为5555)发送【SYN】,其中Seq=j=0。第二次握手,服务器回一个【SYN,ACK】,其中Seq=k=0,Ack=j+1=1。第三次握手,客户端向服务器发一个【ACK】,其中Seq=j+1=1(上一个包序号是j,当前这个包为j+1),Ack=k+1=1。

客户端通过connect建立连接进行三次握手。服务器端三次握手之后调用accept函数,返回文件描述符。

2、数据传输:

如上图所示,数据传输时,发送方(端口号为44882)发送【PSH,ACK】:序号为Seq=j=1,Ack=i=1。接收方接收到数据后,会回一个【ACK】:其中ACK中的Seq=i=1,是收到的【PSH,ACK】中的Ack值,表示是Ack=i=1的确认包;Ack=m=3表示当前收到3号之前序号的包。所以接下来,发送端会继续发送【PSH,ACK】:Seq=m=3,也就是收到【ACK】中的Ack值。可以通过Seq和Ack来判断数据是否丢失,是否需要重传。

3、断开连接

(1)四次握手断开连接

如上图所示,第一次握手,主动断开连接一方(端口号为44882)发送【FIN,ACK】;被动断开连接一方(端口号为5555)接收到【FIN,ACK】后,回一个【ACK】,接着发一个【FIN,ACK】到主动断开连接一方;主动断开连接一方接收到【FIN,ACK】后也会回一个【ACK】,这样四次握手断开连接就结束了。

是不是感觉四次握手很简单,如果你这么想的话你就错了。接下来深入去挖掘断开连接的过程

如上图(网上借鉴过来的,博主写的很好,可以去借鉴一下https://blog.csdn.net/kkgbn/article/details/77859881)所示,主动断开一方close()关闭句柄,发送【FIN,ACK】后,该方这条通路的句柄会处于FIN_WAIT_1状态(可以通过netstat -at命令查看);被动断开一方回复完【ACK】时,该方这条通路的句柄会处于CLOSE_WAIT状态;主动断开一方收到【ACK】后,该句柄会处于FIN_WAIT_2状态;当被动断开一方close()关闭句柄时,会发送【FIN,ACK】,该句柄处于LAST_ACK状态(这个没有验证);主动断开一方收到【FIN,ACK】之后,回一个【ACK】,该句柄会处于TIME_WAIT状态,2ms后回彻底关闭;被断开一方收到【ACK】会彻底断开。

(2)三次握手断开连接

上面是四次握手断开连接,还存在三次握手断开连接的情况(两方同时断开连接),如下图所示

当被断开一方阻塞在recv函数时接收到【FIN,ACK】,此时recv会立刻返回0,被断开连接一方不回复【ACK】而是直接发送【FIN,ACK】。

(3)断开过程的一些细节

被断开连接一方处于CLOSE_WAIT状态和LAST_ACK状态之间,是可以继续发送数据的,但是此时主动断开连接一方处于FIN_WAIT_2,它接收到数据时会发送一个【RST,ACK】,当被断开连接一方再发送数据时,程序会异常退出。

当被断开连接一方一直没有close关闭连接或者程序没有退出,句柄会一直停留在CLOSE_WAIT状态,造成端口不可用;关闭句柄,就会发出【FIN,ACK】,就不能够再发送数据。

 

 

  • 5
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值