面试官:TCP为什么是三次握手?而不是两次或四次...

这是一个很有意思的问题~

首先,我们要知道TCP是全双工的,即客户端在给服务器端发送信息的同时,服务器端也可以给客户端发送信息。而半双工的意思是A可以给B发,B也可以给A发,但是A在给B发的时候,B不能给A发,即不同时,为半双工。单工为只能A给B发,B不能给A发;或者是只能B给A发,不能A给B发。

我们假设A和B是通信的双方。我理解的握手实际上就是通信,发一次信息就是进行一次握手。

  • 第一次握手:A给B打电话说,你可以听到我说话吗?

  • 第二次握手:B收到了A的信息,然后对A说~我可以听得到你说话啊,你能听得到我说话吗?

  • 第三次握手:A收到了B的信息,然后说可以的,我要给你发信息啦!

在三次握手之后,A和B都能确定这么一件事:我说的话,你能听到;你说的话,我也能听到。 这样,就可以开始正常通信了。

注意:HTTP是基于TCP协议的,所以每次都是客户端发送请求,服务器应答,但是TCP还可以给其他应用层提供服务,即可能A、B在建立链接之后,谁都可能先开始通信。

如果两次,那么B无法确定B的信息A是否能收到,所以如果B先说话,可能后面的A都收不到,会出现问题 。

如果四次,那么就造成了浪费,因为在三次结束之后,就已经可以保证A可以给B发信息,A可以收到B的信息;B可以给A发信息,B可以收到A的信息。

三次握手正式情况下做了什么?

第一次握手:

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


第二次握手 :

服务器发回确认包(ACK)应答。即SYN标志位和ACK标志位均为1同时,将确认序号(Acknowledgement Number)设置为客户的I S N加1以.即X+1。

第三次握手:

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

即SYN就是询问:你能听得到吗?ACK就是回到:我能听得到啊。

TCP四次挥手的过程:


四次挥手:

A:“喂,我不说了 (FIN)。”A->FIN_WAIT1

B:“我知道了(ACK)。等下,上一句还没说完。Balabala……(传输数据)”B->CLOSE_WAIT | A->FIN_WAIT2

B:”好了,说完了,我也不说了(FIN)。”B->LAST_ACK

A:”我知道了(ACK)。”A->TIME_WAIT | B->CLOSED

A等待2MSL,保证B收到了消息,否则重说一次”我知道了”,A->CLOSED

这样,通过四次挥手,可以把该说的话都说完,并且A和B都知道自己没话说了,对方也没话说了,然后就挂掉电话(断开链接)了 。

最后也给想软件测试的朋友们分享一份测试资料:

以上内容,对于软件测试的朋友来说应该是最全面最完整的备战仓库了,有需要的朋友关注下方卡片的公众号,免费领取

### TCP三次握手的过程 TCP协议通过三次握手建立可靠的连接。具体来说: - 客户端发起请求,发送带有SYN标志的数据包给服务器,并进入SYN_SEND状态;此时序列号设为x[^1]。 - 服务器接收到该数据包后返回一个带有SYN和ACK标志的数据包作为应答,表示同意通信并设置自己的初始序列为y,同时对客户端的序列号加一确认(即ack=x+1),随后进入SYN_RECV状态[^2]。 - 当客户端收到来自服务端的SYN/ACK响应之后,再回传一次普通的ACK报文给对方用于最终确认,其中包含着对于之前接收消息的认可编号(ack=y+1)。当这一步完成后,双方都进入了ESTABLISHED阶段,意味着一条完整的双向通道已经形成可以开始正常传输应用层数据了。 ```python # Python伪代码展示三次握手流程简化版 client_seq = random.randint(0, 2**32 - 1) # 初始化随机序列号x server_seq = None # 服务器初始化序列号为空 def client_send_syn(): global client_seq send_packet('SYN', seq=client_seq) def server_receive_syn_and_reply_ack(): global server_seq received_data = receive_packet() if 'SYN' in received_data.flags: server_seq = random.randint(0, 2**32 - 1) reply_with_syn_ack(received_data.seq + 1, server_seq) def client_final_confirmation(server_initial_seq): confirm_server_init_seq_is_correct = True if confirm_server_init_seq_is_correct: send_packet('ACK', ack_num=(server_initial_seq + 1)) ``` ### 关于为何需要三次握手的原因 为了确保两端都能够正确无误地建立起连接关系而不丢失任何一方的信息,在计算机网络环境中存在着各种不确定因素可能导致某些分组在网络上传输失败者延迟到达等问题发生。因此采用三步验证机制来保证每一次尝试都能得到及时反馈从而提高整个系统的可靠性。 ### 四次挥手断开连接的理由 由于TCP是一个面向字节流而非长度固定的记录帧的服务模型,所以在结束会话时必须明确告知另一方不再有新的数据要传送出去。为此引入了FIN旗标用来标记某方向上的终止意图。然而仅仅依靠单方面声明还不够充分——还需要等待一段时间以确保所有已发出但尚未被处理过的段落均已被接收者获取到手才行。这就解释了为什么关闭操作要比启动复杂得多,通常涉及到四个独立的动作才能彻底切断联系。 ### 面试中的常见问题 针对上述知识点,面试官可能会询问如下几个方面的问题: 1. 描述一下什么是TCP三次握手?其目的是什么? 2. 如果只做两次握手能否实现可靠连接建立呢?如果不行的话缺少哪部分保障? 3. 解释下四次挥手中的每一个步骤以及它们各自的作用是什么样的. 4. 在实际应用场景里如何优化TCP建连效率减少RTT往返时间的影响?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值