TCP三次握手和四次挥手及wireshark抓取

TCP的三次握手与四次挥手的详细介绍:

三次握手:

第一次握手(SYN=1, seq=x):

  客户端发送客户端发送一个 TCP 的 SYN 标志位置1的,指明客户端打算连接的服务器的端口,以及初始序号 X,保存在包头的序列号(sequence Number)字段里。

第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1):

  服务器发回确认包(ACK)应答。即 SYN 标志位和 ACK 标志位均为1。服务器端选择自己 ISN 序列号,放到 seq 域里,同时将确认序号(Acknowledgement Number)设置为客户的 ISN 加1,即X+1。 发送完毕后,服务器端进入 SYN_RCVD 状态。

第三次握手(ACK=1,ACKnum=y+1):

  客户端再次发送确认包(ACK),SYN 标志位为0,ACK 标志位为1,并且把服务器发来 ACK 的序号字段+1,放在确定字段中发送给对方,并且在数据段放写ISN的+1

发送完毕后,客户端进入 ESTABLISHED 状态,当服务器端接收到这个包时,也进入 ESTABLISHED 状态,TCP 握手结束。

握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。

TCP三次握手和四次挥手及wireshark抓取

三次握手

Wireshark抓取三次握手过程;

在浏览器中输入www.golang.com,通过 ping www.golang.com知道golang的ip是 216.239.37.1, 在wireshark filter中输入ip.src == 216.239.37.1 or ip.dst ==  216.239.37.1 用于过滤出所有跟216.239.37相关的报文。

TCP三次握手和四次挥手及wireshark抓取

可以看到,访问网站时,客户端(浏览器)会建立起三次握手。

第一次握手,由客户端发出。

TCP三次握手和四次挥手及wireshark抓取

SYN=1,seq的值为 f5 75 60 37。

第二次握手,服务器发出。

TCP三次握手和四次挥手及wireshark抓取

ACK=1,seq为 61 d0 be 42, ACKnumber是f5 75 60 38,它是第一次握手的seq(f5 75 60 37)值加1。

第三次握手,客户端发出。

TCP三次握手和四次挥手及wireshark抓取

ACK=1。ACKnumber是61 d0 be 43, 是上一次的seq值加1,第二次握手的seq值是61 d0 be 42.

四次挥手:

与建立连接的“三次握手”类似,断开一个TCP连接则需要“四次握手”。

第一次挥手(FIN=1,seq=x):

  假设客户端想要关闭连接,客户端发送一个 FIN 标志位置为1的包,表示自己已经没有数据可以发送了,但是仍然可以接受数据。发送完毕后,客户端进入 FIN_WAIT_1 状态。

第二次挥手(ACK=1,ACKnum=x+1):

  服务器端确认客户端的 FIN 包,发送一个确认包,表明自己接受到了客户端关闭连接的请求,但还没有准备好关闭连接。发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到这个确认包之后,进入 FIN_WAIT_2 状态,等待服务器端关闭连接。

第三次挥手(FIN=1,seq=y):

  服务器端准备好关闭连接时,向客户端发送结束连接请求,FIN 置为1。发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个ACK。

第四次挥手(ACK=1,ACKnum=y+1):

  客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT状态,等待可能出现的要求重传的 ACK 包。服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。

客户端等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED 状态。TCP三次握手和四次挥手及wireshark抓取

四次挥手

Wireshark抓取三次挥手过程:

TCP三次握手和四次挥手及wireshark抓取

第一次挥手,客户端发出。这次断开连接时客户端发出的,但实际上,客户端和服务器都可以主动发出断开连接。

TCP三次握手和四次挥手及wireshark抓取

seq值为f5 75 6a b4。

第二次挥手,服务端发出。

TCP三次握手和四次挥手及wireshark抓取

seq值为61 d3 6c 82, ACKnumber为f5 75 6a b5, 是第一次挥手的seq值加1。

第三次挥手,服务端发出。

TCP三次握手和四次挥手及wireshark抓取

seq值为61 d3 6c 82, ACKnumber为f5 75 6a b5, 是第一次挥手的seq值加1。

第四次挥手,客户端发出。

TCP三次握手和四次挥手及wireshark抓取

ACKnumber为f5 75 6a b5, 是第2/3次挥手的seq值加1

补充:为什么建立连接协议要三次握手,而关闭连接却是四次握手?

  因为服务端的LISTEN状态下的SOCKET收到SYN报文的建立连接请求后,主机A可以把ACK和SYN(ACK起应答作用,SYN起同步作用)放在一个报文里来发送。但是关闭连接时,当收到主机B的FIN报文通知时,它仅仅表示对方没有数据发送了;但主机B未必将所有的数据都全部发送给主机A了,所以主机B未必会马上会关闭SOCKET,也即主机B可能还需要发送一些数据给对方之后,再发送FIN报文给主机A来表示同意现在可以关闭连接,所以这里的ACK报文和FIN报文多数可以分开发送的。

参考:https://hit-alibaba.github.io/interview/basic/network/TCP.html

上一篇:TCP/IP协议原理学习笔记


下一篇:javascript 异步解析