# 计算机基础
# 一、网络
# 1 UDP
1.1 面向报文
UDP是一个面向报文(报文可以理解为一段段的数据)的协议。意思就是UDP只是报文的搬运工,不会对报文进行任何拆分和拼接操作
具体来说
- 在发送端,应用层将数据传递给传输层的
UDP协议,UDP只会给数据增加一个UDP头标识下是UDP协议,然后就传递给网络层了 - 在接收端,网络层将数据传递给传输层,
UDP只去除IP报文头就传递给应用层,不会任何拼接操作
1.2 不可靠性
UDP是无连接的,也就是说通信不需要建立和断开连接。UDP也是不可靠的。协议收到什么数据就传递什么数据,并且也不会备份数据,对方能不能收到是不关心的UDP没有拥塞控制,一直会以恒定的速度发送数据。即使网络条件不好,也不会对发送速率进行调整。这样实现的弊端就是在网络条件不好的情况下可能会导致丢包,但是优点也很明显,在某些实时性要求高的场景(比如电话会议)就需要使用 UDP 而不是TCP
1.3 高效
- 因为
UDP没有TCP那么复杂,需要保证数据不丢失且有序到达。所以UDP的头部开销小,只有八字节,相比TCP的至少二十字节要少得多,在传输数据报文时是很高效的

头部包含了以下几个数据
- 两个十六位的端口号,分别为源端口(可选字段)和目标端口 整个数据报文的长度
- 整个数据报文的检验和(
IPv4可选 字段),该字段用于发现头部信息和数据中的错误
1.4 传输方式
UDP不止支持一对一的传输方式,同样支持一对多,多对多,多对一的方式,也就是说 UDP 提供了单播,多播,广播的功能
# 2 TCP
2.1 头部
TCP头部比UDP头部复杂的多

对于
TCP头部来说,以下几个字段是很重要的
Sequence number,这个序号保证了TCP传输的报文都是有序的,对端可以通过序号顺序的拼接报文Acknowledgement Number,这个序号表示数据接收端期望接收的下一个字节的编号是多少,同时也表示上一个序号的数据已经收到Window Size,窗口大小,表示还能接收多少字节的数据,用于流量控制
标识符
URG=1:该字段为一表示本数据报的数据部分包含紧急信息,是一个高优先级数据报文,此时紧急指针有效。紧急数据一定位于当前数据包数据部分的最前面,紧急指针标明了紧急数据的尾部。ACK=1:该字段为一表示确认号字段有效。此外,TCP还规定在连接建立后传送的所有报文段都必须把ACK置为一PSH=1:该字段为一表示接收端应该立即将数据 push 给应用层,而不是等到缓冲区满后再提交。RST=1:该字段为一表示当前TCP连接出现严重问题,可能需要重新建立TCP连接,也可以用于拒绝非法的报文段和拒绝连接请求。SYN=1:当SYN=1,ACK=0时,表示当前报文段是一个连接请求报文。当SYN=1,ACK=1时,表示当前报文段是一个同意建立连接的应答报文。FIN=1:该字段为一表示此报文段是一个释放连接的请求报文
2.2 状态机
HTTP是无连接的,所以作为下层的TCP协议也是无连接的,虽然看似TCP将两端连接了起来,但是其实只是两端共同维护了一个状态

TCP的状态机是很复杂的,并且与建立断开连接时的握手息息相关,接下来就来详细描述下两种握手。- 在这之前需要了解一个重要的性能指标 RTT。该指标表示发送端发送数据到接收到对端数据所需的往返时间
建立连接三次握手

- 在
TCP协议中,主动发起请求的一端为客户端,被动连接的一端称为服务端。不管是客户端还是服务端,TCP连接建立完后都能发送和接收数据,所以TCP也是一个全双工的协议。 - 起初,两端都为
CLOSED状态。在通信开始前,双方都会创建TCB。 服务器创建完TCB后遍进入LISTEN状态,此时开始等待客户端发送数据
第一次握手
客户端向服务端发送连接请求报文段。该报文段中包含自身的数据通讯初始序号。请求发送后,客户端便进入 SYN-SENT 状态,x 表示客户端的数据通信初始序号。
第二次握手
服务端收到连接请求报文段后,如果同意连接,则会发送一个应答,该应答中也会包含自身的数据通讯初始序号,发送完成后便进入
SYN-RECEIVED状态。
第三次握手
当客户端收到连接同意的应答后,还要向服务端发送一个确认报文。客户端发完这个报文段后便进入
ESTABLISHED状态,服务端收到这个应答后也进入ESTABLISHED状态,此时连接建立成功。
- PS:第三次握手可以包含数据,通过
TCP快速打开(TFO)技术。其实只要涉及到握手的协议,都可以使用类似TFO的方式,客户端和服务端存储相同cookie,下次握手时发出cookie达到减少RTT的目的
你是否有疑惑明明两次握手就可以建立起连接,为什么还需要第三次应答?
- 因为这是为了防止失效的连接请求报文段被服务端接收,从而产生错误
可以想象如下场景。客户端发送了一个连接请求 A,但是因为网络原因造成了超时,这时 TCP 会启动超时重传的机制再次发送一个连接请求 B。此时请求顺利到达服务端,服务端应答完就建立了请求。如果连接请求 A 在两端关闭后终于抵达了服务端,那么这时服务端会认为客户端又需要建立 TCP 连接,从而应答了该请求并进入
ESTABLISHED状态。此时客户端其实是 CLOSED 状态,那么就会导致服务端一直等待,造成资源的浪费
PS:在建立连接中,任意一端掉线,TCP 都会重发 SYN 包,一般会重试五次,在建立连接中可能会遇到 SYN FLOOD 攻击。遇到这种情况你可以选择调低重试次数或者干脆在不能处理的情况下拒绝请求
断开链接四次握手

TCP是全双工的,在断开连接时两端都需要发送FIN和ACK。
