计算机网络TCP|面试官问:你应该熟知的三次握手和四次挥手中的知识点👇👇

286 阅读9分钟

TCP头格式

image.png

序号(SEQ |单词 序列 sequence) :SEQ是一个32位的数,第一次由计算机自动生成,之后使用会累加1,保证是有序的

确认号(ack| 单词 承认 acknowledge):ack的值是序号+1

SYN(单词 同步序列编号 Synchronize Sequence Numbers) :一位,0/1, 1:表示请求建立连接

ACK(单词 承认 acknowledge): 应答符号,和小写的ack含义不一样,一位,0/1, 1:表示收到了

FIN(单词 结束 finish) : 一位,0/1, 1:表示请求断开连接

简单了解一下tcp的报文头,我们再来理解tcp的三次握手

三次握手

未命名文件 (4).png

第一次握手

客户端发起建立连接的请求SYN =1 ,并且发送自己的序号 SEQ = x ,x代表一个随机数

注意:此时客户端只是发送了请求,它并不知道服务端是否能收到

第二次握手

服务端回复客户端的请求ACK= 1,确认号ack= x+1 告诉客户端下次发送的序号是x+1(这样才能保证信息的传输是有序的), 发送自己的序号SEQ = y,y代表一个随机数

注意:此时服务端已经收到了客户端的信息,但是他不能确认自己所发送的信息是否能够被客户端接收,因此还需要第三次握手来解决这个问题

第三次握手

客户端回复服务端的请求 ACK =1 ,确认号ack= y+1 告诉服务器端下次发送的序号是y+1, 并且发送自己的序号SEQ =x+1

至此,三次握手过程完成,也建立了可靠的传输

四次挥手

未命名文件 (3).png

第一次挥手

客户端发送断开请求FIN=1:表示我需要断开请求,SEQ=x:从建立连接开始,累加到此刻的值,这里使用x表示

注意:此时,客户端确认了本身可以断开连接,但是不能够确认服务端是否可以断开连接

第二次挥手

服务端接收到客户端的断开请求,便发送确认消息,ACK=1,表示:我收到了你的消息,ack=x+1,确认序号,为接收客户端的序号加一

注意:此时,服务端已经能够知道客户端可以断开连接了,但是他还不能确认本身能够断开连接,导致的原因:有正在接收的消息服务端还未接收完成

第三次挥手

服务端发送可以断开连接的请求FIN=1,表示:我可以和你断开连接了,SEQ=y,序号,从建立连接开始,累加到此刻的序号值

注意:此时,服务端确认客户端能够可以断开连接,也确认了本身可以断开连接;客户端确认了本身可以断开连接,但是无法确认服务端能够断开连接,因此需要再次发送确认信号,就有了第四次挥手

第四次挥手

客户端发送确认消息ACK=1:表示:我收到了你的消息,你可以断开连接了,ack=y+1,为接收到服务端发送的序号加一

注意:此刻,尽管客户端已经满足了断开连接的条件,但客户端不会立即断开连接,而是会等待一段时间再断开连接,目的是为了保证服务端能够接收到确认消息。当服务端收到了确认消息之后,已经满足了断开的条件,他会立即断开连接,而客户端等待了一段时间之后也会断开连接。

为什么三次握手

原因1:为了防止已经失效的报文突然又传到服务器,造成服务器资源的浪费

假设使用的是2次握手机制,有一个这样的场景,客户端发送了第一个请求连接并且没有丢失,只是因为网络问题在网络中进行了滞留,由于客户端没有收到服务端的确认报文,就会发起第二次请求连接,这个时候通过2次握手完成了数据的传递,然后关闭了连接,此时在网络中滞留的那次请求连接因为网络畅通后,又到达了服务器端,此时服务器以为是客户端发送的请求连接,进行了确认回复之后,就一直等客户端传输,就这样就一直等啊,等啊.....我也不知道等到什么时候去.....

原因2:两次握手只能保证单向连接是畅通的,因为TCP是一个双向传输协议,只能经历3次握手,才可以确保双方都可以接受对方发送的数据。

为什么要四次挥手

TCP是面向连接的、可靠的传输协议,TCP是全双工模式,这就意味着,

客户端发出FIN报文段的时候,只能表示客户端没有数据要发送了,客户端告诉服务器端它没有数据要发送了,但是这个时候,客户端还是可以接受服务器端发生的数据,当服务器端返回ACK报文段的时候,表示它知道客户端没有数据发送了,但是服务器端还是可以发送数据给客户端的,当服务器端发送FIN报文段的时候,这个时候就表示服务器端也没有数据可以发送了,就会告诉客户端我没有数据发送了,之后客户端发送ACK报文段确认之后,就会愉快的结束这次连接了。

面试回答

思考💡:怎么回答三次握手?

老师我是这么理解的,TCP建立的是以一个面向连接的、可靠的传输协议,三次握手的机制就是为了保证能建立一个安全的可靠的连接,第一次握手是客户端发起的,客户端发送一个SYN=1的报文段,表示它请求建立连接,第二次握手呢是服务器端返回一个ACK= 1 的报文段表示确认客户端发起的请求连接,经过这2次握手之后呢,对于客户端来说,明确了客户端可以发送请求,也可以接受服务器端的响应,但是对于服务器端而言,2次握手是不够的,因为服务器端只知道我能接受客户端的消息,至于我返回的消息客户端收到没有呀?它是不知道;所以就需要进行第3次握手,第3次握手客户端就会返回ACK=1 的确认消息,通过3次握手,不管是客户端还是服务端都知道我既能给对方发消息,也能收到对方的回应,那个这个连接就被安全的建立起来了。

思考💡:怎么回答四次挥手?

老师4次挥手,我简单说一下我的理解:第一次挥手客户端会发送一个FIN=1 的报文段表示它请求断开连接,当服务器收到这个请求之后,服务器端知道了客户端想要和我断开连接,但是服务器端不一定做好了准备,因为客户端做好断开准备的时候,服务器端可能还有数据没有传输完成,它还要继续传输呢,所以第二次挥手,服务器端只会返回一个ACK=1 的确认消息的报文段,就相当于给客户端说:我知道你要断开,但是我啊,还有点数据没有传完,你等我一会好吧,等一会之后呢,也就是第三次挥手,服务器端就会发送一个FIN= 1 的报文段,表示他做好了断开的准备, 那第四次挥手呢,客户端会传一个ACK=1 的确认报文段,经过4次的交流沟通呢,双方都做好了断开的准备,然后就可以断开了。

思考💡:为什么TCP需要握手这个操作?能不能不握手?

其实UDP协议中,是没有握手这个操作的。

这里就引出了 TCP 与 UDP 的一个基本区别, TCP 是可靠通信协议, 而 UDP 是不可靠通信协议。

TCP 的可靠性含义: 接收方收到的数据是完整, 有序, 无差错的。

UDP 不可靠性含义: 接收方接收到的数据可能存在部分丢失, 顺序也不一定能保证。

思考💡:为什么 TCP 就可以实现可靠传输, 而 UDP 不行?

UDP 和 TCP 协议都是基于同样的互联网基础设施, 且都基于 IP 协议实现, 互联网基础设施中对于数据包的发送过程是会发生丢包现象的。

TCP 协议为了实现可靠传输, 通信双方需要判断自己已经发送的数据包是否都被接收方收到, 如果没收到, 就需要重发。 为了实现这个需求, 很自然地就会引出序号(sequence number) 和 确认号(acknowledgement number) 的使用。

发送方在发送数据包(假设大小为 10 byte)时, 同时送上一个序号( 假设为 500),那么接收方收到这个数据包以后, 就可以回复一个确认号(510 = 500 + 10) 告诉发送方 “我已经收到了你的数据包, 你可以发送下一个数据包, 序号从 510 开始” 。

这样发送方就可以知道哪些数据被接收到,哪些数据没被接收到, 需要重发。

参考

# 前端面试——TCP/IP 的三次握手/四次挥手—结尾总结建议自己梳理全文背诵!

# 前端面试---TCP建立连接的三次握手和释放连接的四次挥手

# TCP协议为什么是三次握手而不是两次呢?

# TCP四次挥手(图解)-为何要四次挥手