目录
3.为什么主动方发送ACK确认被动方的断开后要进入TIME_WAIT状态而不是直接关闭?为什么等2个MSL时间?
TCP概念
TCP(Transmission Control Protocol,传输控制协议),这是一个面向连接的协议,在收发数据之前,双方必须建立可靠的连接。
TCP协议设计的初衷
设计一个可靠的连接服务。
关键的字段
seq 序号
ack 确认号
SYN 同步(此字段是标志位)
ACK 确认(此字段是标志位)
FIN 终止(此字段是标志位)
值得一提的事:
seq代表数据包本身的序列号。
ack代表接期望对方继续发送的那个数据包的序列号,值为对方发送的seq字段+1,代表seq+1之前的内容服务端都收到了。
只有双方都收到了自己的seq被对方确认后,才会认为这条信道中消息可靠。
另外
SYN的回传是为了证明发送方到接收方的信道可靠。
ACK的回传是为了证明接收方到发送方的信道可靠。
什么是三次握手?
参考流程图,总的来说,三次握手是客户端从关闭到打开并与服务端建立可靠链接的过程。
三次握手的过程
接下来分别用官话和俗话来介绍下这个过程。
官话版:
第一次握手:客户端从关闭状态到打开,进入发送同步状态,主动发送第一个握手包(内容是【SYN=1,seq=x】,意思是我现在处于同步状态,我的消息是x)给服务端。此时服务端由监听状态进入收到同步状态,并向客户端发送第二次握手包。
第二次握手:客户端继续处于发送同步状态,服务端处于接收同步状态,客户端收到第二个握手包(内容是【SYN=1,ACK=1,seq=y,ack=x+1】,意思是当前我也于同步状态了,我的身份是y,我知道你的消息是x了)之后,立即向服务端发送第三个握手包。
第三次握手:客户端继续处于发送同步状态,服务端正处于收到同步状态,服务端收到第三个握手包(内容是【ACK=1,seq=x+1,ack=y+1】意思是这是最终确认消息,我的消息是x,你的消息是y)之后,客户端和服务端进入连接建立状态的全双工链接成功建立!
俗话版:
场景:客户端和服务端要要建立一个可靠的连接。
第一次握手:
客户端:“我要建立一个连接(标志位:SYN=1),这是我的消息(seq=x)”
第二次握手:服务端:“可以,我知道了等我准备准备(标志位:ACK=1,SYN=1),再确认下你的消息是(ack=x+1),这是我的消息你也留下(seq=y)。
第三次握手:
客户端:“ok,信息没问题,现在做最终确认(ACK=1),你我知根知底(ack=y+1,seq=x+1)”。
服务端:“说正事,借一部说话?”。
什么是四次挥手?
TCP连接是全双工的,所以通信双方必须单独进行关闭。同时保证在双方关闭连接过程中数据不会发生丢失。因此,四次挥手指的就是C/S双方关闭连接的过程。
双方通过发送FIN码来表示自己不再发送数据,但仍可以继续接收。
四次挥手的过程
同样,也分别用官话和俗话来介绍下这个过程
官话版:
第一次挥手:客户端主动断开,发送第一个挥手包(FIN=1,seq=x,我不会再发送消息,我的信息是x),然后从连接建立状态到FIN-WAIT1状态。
第二次挥手:服务端收到客户端的断开请求后,立即进入CLOSE-WAIT状态,同时发送第二个挥手包(ACK=1,seq=y,ack=x+1,这是一条确认消息,我收到了你的信息,这是我的信息是y)。
第三次挥手:服务端发送第三个挥手包(FIN=1,ACK=1,seq=z,ack=x+1,之前你发的x我都收到了,这是一条确认消息z,之后我也不再发送消息。),
第四次挥手:客户端收到服务端的FIN包后,立即向服务端发送第四个挥手包(ACK=1,seq=x+1,ack=z+1,这是双方的之前各自的标识,可以断开连接了),服务端进入关闭状态,客户端进入TIME-WAIT状态。客户端会在2个MSL时间后进入关闭状态。
俗话版:
第一次挥手:客户端发给服务端,说:“老夫准备关闭连接,不会再发任何消息了”。
第二次挥手:服务端发给客户端,说:“等等,我还有消息要发,先别挂,等我通知”。
第三次挥手:服务端发给客户端,说:“ok,我完事了,后面也不再发任何消息了,可以断开了吧?”
第四次挥手:客户端发给服务端,说:“我知道了,挂吧”。服务端断开连接,客户端等待两个最大报文时间后也断开。
看完了上述内容,思考以下问题:
1.为什么是三次握手?而不是两次?
首先说结论:为了避免连接资源浪费。
为什么是3次?
问题本质是 信道是不可靠的,如果要在不可靠信道上传输可靠数据时,理论上所要求的的最小握手次数是三次,即让通信双方确认彼此收到了对方的消息。
为什么2次会浪费?
C端(Client 端)发出的第一个连接请求报文因网络原因发生滞留后失效, 但最终延迟到达S端(Server 端)。导致S端误以为是新的请求而同意连接,此时客户端并未连接,服务端持续监听资源浪费。
2.为什么是四次挥手?而不是三次?
为什么是四次?
其实就是主动方的两次挥手包和被动方的两次挥手包。(这里用主动和被动,是因为我们有理由相信C/S端都存在主动断开的情况,只是普遍讨论的是客户端主动断开,这里稍强调一下)
主动方 第一次是通知对方,我不发消息了,你准备下断开吧。
第二次是通知对方,现在一切准备好了,你可以断开了。
被动方的 第一次是通知对方,我还没弄完可能还要稍等下,等我通知。
第二次是通知对方,我弄完了,你可以断开了。
显然,本质问题一览无余:不说拜拜就挂电话,不礼貌也不靠谱。
TCP协议设计的初衷就是可靠,显然,它需要通信双方有礼貌地互相道别,保证下次见面不至于尴尬。
如果是三次?
存在这种情况,也在协议考虑范围内,但前提是在收到主动方的断开请求后,被动方在连接上已经没有Pending的消息了(这时被动方会把ACK和FIN一起给主动方,等主动方确认后断开)。
如果有,被动方消息没发完,就可能造成数据丢失的情形。
3.为什么主动方发送ACK确认被动方的断开后要进入TIME_WAIT状态而不是直接关闭?为什么等2个MSL时间?
TIMEWAIT状态保证了2点:
a、确保了全双工通信的可靠断开:主动方的ACK消息丢失后,被动方会重发FIN。这是TIMEWAIT状态保证了主动方能再次收到FIN后重传ACK,让被动方成功。
b、避免用相同源端口和目标端口创建新连接时收到旧连接姗姗来迟的数据包,造成数据错乱。
2个MSL时间的缘由?
1MSL确保主动挥手方最后的一个ACK 报文能到达对方
1MSL确保对方没有收到 ACK后, 重传的 FIN 报文可以到达。
4.如果客户端或者服务端突然挂掉,怎么办?
心跳机制保活
5.TCP和UDP的区别?
a、TCP靠谱,UDP不靠谱。TCP依赖连接,UDP无连接。
b、TCP保质(主要有一些措施如:三握四挥,校验,丢包重传,序号,滑动窗口),UDP保量(实时性很好,容易失真)。
c、TCP效率低,UDP效率高。
d、TCP一对一,UDP一对一、一堆多、多对一、多对多都可以。