什么是TCP中三次握手和四次挥手

简述

该题主要是考察网络基础,属于很常规的题目,而且问到的频率很高哦。

答案

三次握手:

  • 第一次: 客户端向服务器发送连接请求,这时候会发送一个sync(i)包,同时客户单进入到sync_send状态
  • 第二次:服务端收到了客户端的sync请求,回复一个sync包,包中携带ack(i+1)和服务端的sync(j)信息,服务端进入sync_recv状态
  • 第三次:客户端收到服务端的sync包,向服务端发送ack(j+1)包,该包发送完毕后,并且服务端收到ack包后,则双方进入establish状态,即连接建立

如图所示:

TCP中三次握手和四次挥手

有个形象的例子, A和B打电话:

A:  喂,你那边可以听见么?
B:  可以听到,你可以听见么?
A:  可以听见。

四次挥手:

由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。

这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。

首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

注意:中断连接端可以是客户端,也可以是服务端,这里以客户端主动断开为例来说明:

  • 第一次: TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。
  • 第二次:服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
  • 第三次:服务器关闭客户端的连接,发送一个FIN给客户端。
  • 第四次:客户端发回ACK报文确认,并将确认序号设置为收到序号加1。

如图所示:

TCP中三次握手和四次挥手

有个形象的例子, A和B挂电话为例子:

A:  喂,我这边说完了,你说完了吧?
B:  是的
B:我挂了啊?
A:  收到。(B挂电话进入close状态)
A由于不确定B是否已经挂了电话,要等两个最大报文段生存时间关闭

相关问题

问题1. 为什么连接的时候是三次握手,关闭的时候却是四次握手?

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

问题2. 为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。另一方面是为了保证在2MSL期间,该连接的本地端点地址(IP+PORT)不被再次使用,避免可能的较早连接请求到达,被误认为时新连接请求。


相关主题: