tcp的三次握手四次挥手

tcp的三次握手四次挥手_第1张图片
image.png
  • 名词解释
    SYN: synchronization(同步)在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文。对方若同意建立连接,则应在响应报文中使SYN=1和ACK=1. 因此, SYN置1就表示这是一个连接请求或连接接受报文。

ACK: acknowledgement(确认:告知已收到) TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1

FIN: finish(结束)即终结的意思, 用来释放一个连接。当 FIN = 1 时,表明此报文段的发送方的数据已经发送完毕,并要求释放连接。

如果要考察HTTP,我觉得问下HTTP请求/响应报文的组成可能会更好.
HTTP请求报文组成:请求行+请求头+请求体
HTTP响应报文组成:响应行+响应头+响应体
请求行: 请求方法(HEAD/GET/POST) + 请求URL + HTTP协议版本
响应行: HTTP协议版本 + 状态码 + 状态码描述
请求头: 比如客户端的Cookie和User-Agent就放在这里.
响应头: 比如服务器的Set-Cookie和Server信息就放在这里.
请求体: 比如客户端POST的数据就放在这里(对比:GET的数据放在请求行的URL里).
响应体: 比如服务器返回的HTML和JSON数据就放在这里.

  • 三次握手--建立连接
  1. 简单解释

建立TCP连接时会发生:三次握手(three-way handshake)
firefox > nginx [SYN] 我想给你发数据,可以吗?
nginx > firefox [SYN, ACK] 我想给你发数据,可以吗?
firefox > nginx [ACK] 我想给你发数据,可以吗?

  1. 图片解释


    tcp的三次握手四次挥手_第2张图片
    image.png
  1. 详细解释


    tcp的三次握手四次挥手_第3张图片
    image.png

第一次握手:主机A发送位码为SYN=1,随机产生seq number= 1234567的数据包到服务器,主机B由SYN=1知道,A要求建立联机,
主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),SYN=1,ACK=1,随机产生seq=7654321的包
第二次握手:主机A收到后检查ack number是否正确,即是否是第一次发送的seq number+1,以及位码ACK是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),ACK=1
第三次握手:主机B收到后确认seq值与ACK=1则连接建立成功。
完成三次握手,主机A与主机B开始传送数据。

  1. 问题
    连接建立,为什么要进行三次握手呢(两次确认)。
    建立三次握手主要是因为A发送了再一次的确认,那么A为什么会再确认一次呢,主要是为了防止已失效的连接请求报文段又突然传送给B,从而产生了错误
    所谓“已失效的连接请求报文”是这样产生的,正常情况下,A发出连接请求,但是因为连接报文请求丢失而未收到确认,于是A再重传一次连接请求,后来收到了请求,并收到了确认,建立了连接,数据传输完毕后,就释放链接,A共发送了两次连接请求报文段,其中第一个丢失,第二个到达了B,没有“已失效的连接请求报文段”,但是还有异常情况下,A发送的请求报文连接段并没有丢失,而是在某个网络节点滞留较长时间,以致延误到请求释放后的某个时间到达B,本来是一个早已失效的报文段,但是B收到了此失效连接请求报文段后,就误以为A又重新发送的连接请求报文段,并发送确认报文段给A,同意建立连接,如果没有三次握手,那么B发送确认后,连接就建立了,而此时A没有发送建立连接的请求报文段,于是不理会B的确认,也不会给B发送数据,而B却一直等待A发送数据,因此B的许多资源就浪费了,采用三次握手的方式就可以防止这种事情发生,例如刚刚,A不理会B,就不会给B发送确认,B收不到A的确认,就知道A不要求建立连接,就不会白白浪费资源
  • 四次挥手--断开连接
    中断连接端可以是Client端,也可以是Server端。
  1. 简单解释

关闭TCP连接时会发生:四次挥手(four-way handshake)
firefox > nginx [FIN] 我要关闭连接了
nginx > firefox [ACK] 知道了,等我发完包先
nginx > firefox [FIN] 我也关闭连接了
firefox > nginx [ACK] 好的,知道了

  1. 详细解释


    tcp的三次握手四次挥手_第4张图片
    image.png

第一次挥手:假设Client端发起中断连接请求,也就是发送FIN报文。
第二次挥手:Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了",但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,"告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息"。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。
第三次挥手:当Server端确定数据已发送完成,则向Client端发送FIN报文,"告诉Client端,好了,我这边数据发完了,准备好关闭连接了"。
第四次挥手:Client端收到FIN报文后,"就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。“,Server端收到ACK后,"就知道可以断开连接了"。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!

  1. 【问题】为什么要等待呢?

为了这种情况: B向A发送 FIN = 1 的释放连接请求,但这个报文丢失了, A没有接到不会发送确认信息, B 超时会重传,这时A在 WAIT_TIME 还能够接收到这个请求,这时再回复一个确认就行了。(A收到 FIN = 1 的请求后 WAIT_TIME会重新记时)
另外服务器B存在一个保活状态,即如果A突然故障死机了,那B那边的连接资源什么时候能释放呢? 就是保活时间到了后,B会发送探测信息, 以决定是否释放连接

【问题】为什么连接的时候是三次握手,关闭的时候却是四次握手?
答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

你可能感兴趣的:(tcp的三次握手四次挥手)