TCP连接的三次握手和四次挥手(详解)

前言:运输连接有三个阶段:连接建立、数据传送和释放连接

TCP连接为什么需要握手

TCP为了实现可靠传输,发送方和接收方始终需要同步( SYNchronize )序号。 但是, 序号并不是从 0 开始的, 而是由发送方随机选择的初始序列号 ( Initial Sequence Number, ISN )开始 。 由于 TCP 是一个双向通信协议, 通信双方都有能力发送信息, 并接收响应。 因此, 通信双方都需要随机产生一个初始的序列号, 并且把这个起始值告诉对方。所以就需要通过多次发送数据报(握手)的方式,传达一些连接信息以及用来同步的序列号等

在这里插入图片描述

上图为TCP报文段的首部格式

握手和挥手时的一些必要数据的含义
  • 序号 seq:TCP是面向字节流的,下一个TCP连接中传送的字节流的每一个字节都按顺序编号。序号是指需要发送的某段报文的序号,但是这需要基本上不是连续的,因为该序号是所发送报文的第一个字节的序号,但是报文却不是只有一个字节,比如一段报文的序号字段指是301,而携带的数据有100字节,这就表明该数据段的序号是3.0,最后一个字节的序号是400,而下一段发送的报文数据的序号就是401了,他们虽然是连续的报文,但却不是连续的序号,如301和401;
  • 确认号 ack(小写的ack,且大小有别,后面会给出):期待收到对方下一个报文段的第一个数据的序号。ack是多少,表明你下一次期望收到的序号,即拿上面seq的举例子,如果现在收到的序号是301,而数据长度是100,所以你下一次期望收到的序号就是从401开始的,即确认号ack = seq(下一次期待的报文序号)= 401,ack也会等于上一个报文段的最后一个字节的序号+1;
  • 确认号ACK(大写的,大小有别和上面的小写的不要搞混): 仅当ACK=1时(ACK只占一位的数据即1bit,只能是1,或者是0),ack才有效,否则ack无效,在连接建立后,所有报文段的ACK都必须是1;
  • 同步SYN: 连接时用来同步序号,当SYN=1(SYN只占一位的数据即1bit,只能是1,或者是0)且ACK=1时,表明这是一个连接请求报文段。若对方同意连接,则在响应的报文段中让SYN=1,ACK=1;
  • 终止FIN:用来释放一个链接,当FIN=1时,表明此报文段的发送方的数据已经发完毕了,要求释放链接;

三次握手

TCP连接的建立采用客户服务器方式,主动发起建立连接的应用叫做客户(client),而被动等待连接的应用叫做服务器(server)
在这里插入图片描述
最初,两端的进程都处于CLOSED(关闭)状态,(本例子默认左边是发起连接的,即左边是客户端)

一开始,右边的TCP服务器进程先创建传输控制块TCB(存储每一个连接的一些重要信息),准备接收请求,然后加入LISTEN(收听)状态,等待请求‘

第一次握手

左边的TCP客户进程也先创建一个TCB,然后在打算建立连接时,向服务器发出连接请求报文,这时同步位SYN = 1,同时携带一个初始序号 seq = x (前面已经讲过序号都是随机的),在TCP规定中,SYN的报文段(即SYN = 1的报文段)不能携带数据,但是也需要消耗一个序号seq;发送完后,客户就进入SYN-SENT(同步已发送)的状态

第二次握手

服务器收到连接亲求的报文段后,如果同意建立连接,则向客户发送确认,在确认的报文段中,SYN = 1ACK = 1;确认号ack = x + 1(因为在第一次握手的请求里面不携带数据,所以x + 1就是下一条报文段数据);且还要发送自己的一个初始序号seq = y,且这个和第一次握手一样,也不能携带数据,但是要消耗一个序号;这时服务器进入SYN-RCVD(同步收到)状态

第三次握手

客户收到服务器的确认后,还需要向服务器发送确认,报文段的ACK = 1;确认号ack = y+ 1,自己的序号seq = x + 1(等于第二次握手的ack);TCP连接已经建立,客户进入ESTABLISHED(已建立连接)状态,服务器收到后,也进入ESTABLISHED状态

可以四次握手吗?

可以;在服务器发送给客户的报文可以拆开为两端,即,先发送一个确认报文段,(ACK = 1,ack = x + 1),然后再发送一个同步报文段(SYN = 1;seq = y),这就变成了四次握手了,但是这样效果是一样的,所以就没必要了

可以两次握手吗?

不可以

原因1:因为在客户发起请求时,如果客户的第一次请求出现了一些错误,如出现延迟这时客户就再发送一次,然后服务器收到了,然后做完交易了,也轻轻松松释放了连接;但是不巧的是,因为客户的一次连接亲求这个时候到了服务器了,但是服务器会认为你还是要发送亲求,如果这个时候只有两次握手,那么服务器这个时候就和客户建立了连接了,但是客户交易都做完了,所以压根就就理睬服务器了,但是服务器又一直在等,这样就造成了资源的浪费,所以一定需要第三次的再次确认,这样服务器因为没收到客户的再次请求,所以就不建立连接了;

原因2:如果没有第三次, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认,即服务器就收不到自己的确认号ack,这时在和客户进行交易时,压根就不知道自己需要发送的序号seq,但是因为为了实现可靠数据传输, TCP 协议的通信双方, 都必须要维护一个序列号, 以标识发送出去的数据包里面, 哪些是已经被对方收到的。 三次握手的过程即是客户与服务器的连接建立也是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤

四次挥手

在这里插入图片描述
数据传输结束后,通信的双方都可以释放连接,且现在客户和服务器都处于ESTABLISHED状态

第一次挥手

客户的进程先向其TCP发出连接释放报文段,并停止再发送数据,主动关闭连接,客户把释放连接的报文段首部的终止控制位FIN = 1;且序号seq = u(等于客户前面发送的数据的最后一个字节的序号加1);然后客户进入FIN-WAIT-1(终止等待 1)状态,等待服务器的回复;FIN和SYN一样,即使不携带数据,也是需要消耗一个序号的;

第二次挥手

服务器收到客户的连接释放亲求后,即发出确认,确认号ack = u + 1,而这个段自己的序号seq = v(等于服务器前面发送的数据的最后一个字节加1),然后服务器进入CLOSE-WAIT(关闭等待)状态;TCP服务器进程通知高层应用进程,所以客户到服务器的连接就释放了,这时的TCP处于半关闭(half-close)状态,即,你客户不能再发数据给我了,但是如果我服务器还要发数据,客户仍然需要接收,即服务器到客户的连接没有关闭,所以称为半关闭状态,且可能持续一段时间

客户在收到服务器的确认后,就进入FIN-WAIT-2(终止等待 2)状态,等待服务器发出释放连接的报文

第三次挥手

如果服务器已经没有数据要发送给客户了,其应用进程就通知TCP释放连接,这时发出一个报文段且FIN = 1;自己的seq = w(在半关闭的状态可能又发送了一些数据,所以seq可能变了),且必须重复第二次挥手时的确认号ack = u + 1;这就服务器就进入了LAST-ACK(最后确认)状态了,等客户的确认

第四次挥手

客户收到服务器的连接释放亲求报文段后,必须对次发出确认,将确认报文段的ACK = 1,确认号ack = w + 1;,而自己的序号seq = u + 1(因为前面发送的FIN报文段需要消耗一个序号);然后进入TIME-WAIT(时间等待)状态;在这里TCP的连接还没有释放掉,必须经过时间等待计时器(TIME-WAIT timer)设置的时间2MSL后,客户才进入CLOSED状态,但服务器收到后,就进入CLOSED状态,不用等待

客户为什么需要等待2MSL时间?

原因1:为了保证客户发送的最后一个ACK确认报文段能够到达服务器;因为如果服务器因为某些原因没有收到最后的确认报文段,这样服务器就无法正常进入CLOSED的状态了,在等待时间内,客户还可以重新发送,且重启时间等待计时器

原因2:防止在握手里面由于某些原因广域晚到的保温到出现在本连接里面,因为在2MSL的时间内,就可以使本连接持续的时间内所有产生的报文都消失在网络中

挥手至少需要4次,因为释放连接是单方面的发出释放请求,然后等待对方做出确认,即一方的释放连接请求,至少是两次挥手,所以加起来至少四次

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值