(1)UDP是无连接的:发送数据之前不需要像TCP一样建立连接,也不需要释放连接,所以减少了发送和接收数据的开销
(2)UDP 使用尽最大努力交付:即不保证可靠交付
(3) UDP是面向报文的。UDP在发送数据时会将数据划分为一个个报文(既不合并,也不分拆),每个报文都有自己的边界。这意味着在接收端,可以轻松地将每个报文视为独立的消息。这有助于接收端明确地识别每个消息的开始和结束。
(4)UDP支持一对一、一对多、多对一的交互通信。
(5)UDP首部开销比较小,只有八字节。
用户UDP由两部分组成:分别是首部+数据部分。首部包括了源端口、目标端口、长度以及校验和(这四项是八字节)。
包括源IP地址、目标IP地址、UDP长度这些是IP首部,可以称伪首部。
长度:UDP用户数据报文的长度,最小值为8
校验和:检验UDP正确性的
每一部分如下所示
UDP(User Datagram Protocol)常用于需要高性能、低延迟和快速数据传输的场景,尤其是在网络应用中,需要处理实时性要求较高、可容忍一定数据丢失的情况。以下是一些常见的UDP使用场景:
实时多媒体流: UDP适用于音频和视频流传输,如实时音频和视频通话、音视频会议、在线游戏的语音通信等。在这些场景中,速度和低延迟比数据的100%可靠性更为重要。
DNS解析: 域名系统(DNS)通常使用UDP来查询域名解析,因为DNS查询需要快速的响应时间,而且可以容忍一些数据包的丢失。
网络广播和多播: UDP支持广播和多播通信,这使得它在需要将数据广播到多个接收者的场景中非常有用,如视频直播和网络广播。
实时定位服务: 实时定位和地理位置服务(如GPS定位)使用UDP来快速传递位置信息,以确保地理位置信息的及时性。
传感器数据: UDP适用于传感器网络,其中传感器数据需要快速传输并及时处理,但不一定需要100%的数据可靠性。
网络游戏: 在在线游戏中,UDP通常用于快速传输游戏状态和玩家输入,因为延迟是游戏性能的关键因素。
具体的报文格式:
源端口和目标端口无需多言;
序号和确认号:保证TCP协议的可靠传输,
序号(Sequence Number):用于标记TCP数据包中的字节流序列号
每个TCP数据包都包含一个序号,它表示发送端发送的字节流的第一个字节的序列号。
接收端使用序号来将TCP数据包按顺序重新组装,以确保数据的顺序交付。如果数据包丢失或乱序到达,接收端可以使用序号来重组数据。
序号还用于检测重复数据包,因为每个数据包都有一个唯一的序号。
确认号(Acknowledgment Number):
确认号字段表示接收端期望接收的下一个字节的序列号。它指示了接收端已成功接收并准备好接收序号为确认号的字节之后的数据。
发送端会根据确认号来知道哪些数据已经被接收,哪些数据还需要重传。如果发送端收到确认号,它会知道接收端已成功接收数据,并可以继续发送下一批数据。
1) 第一次握手(SYN,Seq=X(序列号))
- 客户端发送一个带有SYN(同步序列编号)标志的TCP数据包给服务器
- 数据包中包含一个初始序列号Seq=X
- 客户端进入“SYN_SENT”状态等待服务器确认
2) 第二次握手 (SYN,ACK,Seq=Y, Ack=X+1)
- 服务器端接收到客户端请求后,发回一个确认(ACK)数据包。
- 这个数据包中包含了SYN、ACK标志,表示服务器已经接收了客户端的请求,并准备好建立连接。
- 服务器也会分配一个自己的初始序列号Seq=Y,来表示服务器发送的数据初始序列号
- 通过ACK字段中的Ack=X+1表示自己接收到的Seq为X
- 同时发送Ack=X+1表示,服务器端下一个期望接收到的Seq序列号为Seq=X+1
3) 第三次握手(ACK,Ack=Y+1,Seq=X+1)
- 接收到Seq后,返回确认信息Ack=Y+1,下一个期望接收到的序列号为Y+1
- 服务器接收到客户端的确认后,进入"ESTABLISHED"状态,而客户端也进入"ESTABLISHED"状态。
1)第一次挥手(客户端发送FIN)
第一次挥手:A 说“我没啥要说的了”
第二次挥手:B 回答“我知道了”,但是 B 可能还会有要说的话,A 不能要求 B 跟着自己的节奏结束通话
第三次挥手:于是 B 可能又巴拉巴拉说了一通,最后 B 说“我说完了”
第四次挥手:A 回答“知道了”,这样通话才算结束。
这个题重点在于回答三次握手和两次握手的区别。(四次握手或者更多你就可以直接说,如果三次握手能够解决问题,四次、五次更多的连接就是浪费资源,没必要)
第一个原因避免历史连接。
RFC 793 指出:The principle reason for the three-way handshake is to prevent old duplicate connection initiations from causing confusion.
两次握手场景下,客户端先后发送了两端连接请求,Seq=X和Seq=Y,那由于Seq=Y是后发送的,所以客户端更希望自己收到的是Ack=Y+1,但是Seq=X会先到达服务端,服务端会根据SYN和Seq=X,向客户端回消息,Ack=X+1,此时,客户端会认为连接已经建立(两次连接嘛)。所以开始向客户端发送消息。客户端发现自己收到了Ack=Y+1知道不是自己期望的,所以会要求连接中断。
在这个场景下服务端向客户端发送了无用的数据
第二个原因维持双向的序列号,
两次握手场景中,服务端发送了ACK和Ack=X+1后就开始发送数据了,此时服务端不知道客户端有没有收到自己的确认消息。不能维持双向连接的基本需求。
客户端调用close函数,就会向服务端发送FIN报文,试图与服务端断开连接,此时客户端进入了Fin_WAIT状态。
如果客户端一直没有收到Ack应答报文,就会触发超时重传机制(有最大次数限制)。超过最大次数,就不再发送报文,直接进入close状态。
当接收到客户端的FIN报文,就会先回应一个ack报文,此时服务端进入了CLOS_WAIT状态。
客户端不会收到服务器的确认消息,所以客户端仍然可以发送数据。
服务端需要等待客户端的重传FIN以开始继续挥手。
服务器发送带有FIN标志的数据包以请求关闭连接,但是数据包丢失。
客户端不知道服务端已经请求关闭连接,仍然可以发送数据
服务器需要等待客户端的确认ACK,然后重传FIN以开始新的挥手过程。
客户端接收到服务器的FIN后,发送带有ACK标志的数据包,但该数据包丢失
服务器不知道客户端已经确认关闭连接,但仍然不能再发送数据。
客户端可能需要等待服务器的FIN重传,然后重新发送ACK以继续挥手过程。
1) 保证双方能够正常关闭:如果没有TIME_WAIT状态的话,客户端最后一次发送ack应答报文后就进入了close阶段。如果服务端没有收到ack报文的话,就会重传FIN报文,而此时客户端已经close了,就会返回一个RST错误报文。
而有了TIME_WAIT状态的话,客户端并不会着急关闭,而是等待了2MSL再关闭,这样的话就算重传的fin报文也能正确响应,保证了服务端的正确关闭
2)防止旧连接的数据干扰新连接:假设没有TIME_WAIT状态,那么在关闭连接前有个报文被延迟了。关闭后,又重新建立了相同四元组的连接,此时前一个被延迟的数据包到达了(没有到达最大生存时间),并且正好在接收窗口内,那么服务端就会错误接收,使得数据混乱。
而TIME_WAIT就是帮助客户端和服务端删除两边的一个历史都被正常丢弃,不干扰新的连接
第四次挥手时,客户端发送给服务器的 ACK 有可能丢失,如果服务端因为某些原因而没有收到 ACK 的话,服务端就会重发 FIN,如果客户端在 2*MSL 的时间内收到了 FIN,就会重新发送 ACK 并再次等待 2MSL,防止 Server 没有收到 ACK 而不断重发 FIN。
超文本传输协议(HTTP,HyperText Transfer Protocol) 是一种用于传输超文本和多媒体内容的协议,主要是为 Web 浏览器与 Web 服务器之间的通信而设计的。当我们使用浏览器浏览网页的时候,我们网页就是通过 HTTP 请求进行加载的。HTTP 使用客户端-服务器模型,客户端向服务器发送 HTTP Request(请求),服务器响应请求并返回 HTTP Response(响应)。
HTTP 协议大部分是基于 TCP 协议(注HTTP3.0是基于UDP的,HTTP2.0和HTTP1.0是基于TCP协议的), HTTP 协议是”无状态”的协议,它无法记录客户端用户的状态,一般我们都是通过 Session 来记录客户端用户的状态。
HTTP(Hypertext Transfer Protocol):
HTTPS(HTTP Secure):
首先这里我们需要巩固一下HTTP的典型特征
- 明文的、文本协议,而不是2进制协议,人可以看懂里面的聂荣
- 消息是一来一回的。即客户端发起一个TCP连接,在连接上面发一个HTTP Request到服务器,服务器返回一个HTTP Response,然后连接关闭。每来一个请求久开一个连接,请求完了久关闭连接。
根据上面的特性其实HTTP最典型的问题就是性能问题,连接的建立和关闭都是耗时的。对于一个网页来说,除了页面本身的请求,页面里的JS、CSS、img资源都是一个个HTTP请求。一个页面有十几个资源甚至是几十个都是很常见的。这种连接+关闭是非常消耗时间的。