文章参考
UDP的特点
UDP全程用户数据报协议,它具有以下特点:
- 面向无连接。它不需要像TCP一样需要三次握手才能建立连接,而是想发送数据即发送数据。
- 面向报文。发送数据时,对应用层传递下来的报文,UDP协议直接为其装上UDP协议头即交付给网络层,而不进行拆分和拼接。
- UDP支持一对一、一对多和多对多的传播方式。
- 不可靠。因为没有拥塞控制,发送数据是以一个恒定的速率发送的,当网络状态不好时就会出现丢包。但这个设置的好处是实时性高,适用于电话会议、网络游戏等场景。
- 首部开销小,UDP报文的首部包括源端口+目标端口+长度+报文校验和,总共8个字节,传输报文的效率高。
TCP的特点
- 面向连接,发送数据之前必须在两端建立连接,建立连接的方法是“三次握手”,也为数据的可靠传输打下基础
- 一对一连接:每条TCP传输只能有两个端点
- 面向字节流:TCP不能像UDP一样对独立传输一个报文,会对报文进行拼接或拆分,然后以字节流的方式进行传输
- 可靠传输:提供无差错、不丢包、不重复和按序传输的功能
- 提供拥塞控制:在网络出现拥塞时,TCP能减小向网络中注入数据的速率和数量,缓解拥塞
- 提供全双工通信:TCP传输允许通信双方任何时候都能发送数据
- 头部开销大:最小20字节
TCP三次握手的流程
第一次握手:客户端向服务器端发送连接请求报文(SYN),报文中包含自己的数据通信初始序列号(seq=1000),发送后即进入SYN-SEND状态。
第二次握手:服务器端收到客户端发来的连接请求报文,并同意连接后,向客户端发送应答报文(SYN+ASK),报文中也包含自身的数据通信初始序号(seq=2000,ask=1001),发送后即进入SYN-RECEIVED状态。
第三次握手:客户端收到服务器端的应答报文后,应知晓服务器端自己已收到应答,因此再发送确认报文(SYN=1001,ASK=2001),发送后即进入ESTABLISHED状态,服务器端收到确认报文后也进入ESTABLISHED状态,此时连接正式建立。
为什么一定是三次握手,不能是两次握手?
三次握手是为了防止服务器端收到失效的连接请求报文。
如果客户端第一次握手发送的连接请求报文由于网络迟滞,晚点到达了服务器端,服务器端返回应答消息到客户端,但此时已经过了客户端的连接等待时长,客户端收到的也是一个无效的应答报文,他没有数据要发,但服务器就一直在傻傻等候,浪费了资源。
TCP四次挥手的流程:
由于TCP连接是全双工的,所以通信双方都要发送FIN和ACK
第一次握手:客户端认为数据发送完毕,需要向服务端发送连接释放的请求(FIN+ACK),进入FIN-WAIT_1状态
第二次握手:服务器端收到连接释放请求后,告诉应用层要施放TCP连接,然后会发送ACK包,进入CLOSE_WAIT状态,表明a客户端到服务器的连接已经释放,但服务器仍可向客户端发送数据
第三次握手:服务器端的数据也发送完毕后,向客户端发送连接释放请求(FIN+ACK),然后进入LAST_ASK状态。
第四次握手:客户端收到服务器端的释放请求后,向服务器发送确认应答(ACK),此时A进入TIME_EAIT状态,该状态持续2MSL,超过该时间段就进入CLOSED状态,当服务器收到确认应答后,也进入CLOSED状态
为什么不能是三次挥手?
因为一旦连接建立了起来,两边既是发送,也是接收,如果一方不发送了但还可以接收,也不可以断开连接,要等另一方真的把数据都传输完,才能结束。
为什么连接的时候是三次握手,关闭的时候却是四次握手?
因为连接建立时,客户端发送SYN连接请求后,服务器端直接发送SYN+ACK报文。而释放连接时,服务器收到客户端的FIN报文后,不能直接关闭端口,只能先回复一个ACK报文,告诉客户端“你发送的FIN报文我已经收到了”,然后必须等待自己的资源全部发送完毕后才能发送FIN报文
为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。
如果已经建立了连接,但是客户端突然出现故障了怎么办?
TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。