计算机网络 --- TCP 与 UDP

x33g5p2x  于2022-05-05 转载在 其他  
字(3.2k)|赞(0)|评价(0)|浏览(469)

1. UDP

1.1 UDP 首部的格式

  • 源端口号: 发送端端口号
  • 目的端口号: 接收端端口号
  • UDP长度: 整个UDP的首部长度 与 数据的长度之和
  • 校验和: 检测UDP数据报文在传输过程中是否有错,错误就丢弃。

1.2 UDP的特点

  1. 无连接
    知道了对方的 IP 和 端口号 就能进行传输,不需要建立联系.
  2. 不可靠传输
    没有任何的安全机制,发送端发送数据之后,即使网络拥堵或者传输中出现丢包的情况,UDP也不会负责去重发.
  3. 面向数据报
    应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并.
  4. 全双工
    UDP 的socket 既能读又能写,就是全双工
  5. 大小受限
    UDP协议中,首部有一个16位最大长度, 相当于 一个 UDP 传输的数据最大位 64K (包含UDP首部)

2. TCP

2.1 TCP首部格式

  • 源端口号: 发送端端口号
  • 目的端口号: 接收端端口号
  • 序列号: 发送数据的位置.每发送一次数据就累加一次该数据字节数的大小.
  • 确认应答号: 下一次应该收到的数据的序列号.
  • 首部长度:表示该TCP头部有多少个32位bit(有多少个4字节);所以TCP头部最大长度是15 * 4 = 60
  • 保留: 为了以后拓展时使用,其长度位4位.一般设置为0.即使收的包在该字段不是0,也不会丢弃
  • 控制位: 每一位从左至右分别为 CWR, ECE, URG, ACK, PSH,RST,SYN,FIN.

ECE: 为1时,表示网络拥堵
URG: 为1时,表示包中需要紧急处理的数据,
ACK: 为1时,确认应答的字段变为有效
PSH: 为1时,需要将收到的数据立刻传入上层应用协议,为0时,则不需要立刻传而是先进行缓存
RST: 为1时,表示与TCP连接中出现异常必须强制断开连接,复位报文段
SYN: 为1时,表示希望建立连接.带SYN标识的称为同步报文段
FIN: 为1时,表示不会再有数据发送,希望断开连接.带FIN标识的为结束报文段

  • 窗口大小: 通知从相同TCP首部的确认应答号所指位置开始能够接收的数据大小(8位字节).
  • 校验和:: 目的是为了发现TCP首部和数据在发送端到接收端之间发生的任何改动。如果接收方检测到检验和有差错,则TCP段会被直接丢弃。
  • 紧急指针: 在URG控制位为1时有效

2.2 TCP的特点

  1. 有连接
  2. 可靠传输
  3. 面向字节流
  4. 全双工

2.3 序列号 与 确认应答 (提高可靠性)

在TCP中,当发送端发送一个数据到主机中时,接收端就会返回一个已收到的消息通知,这个消息通知就叫确认应答(ACK)
例如,小明跟小强聊天,
小明 -> 小强 : 明天出去玩?
小明 <- 小强 : 收到!
小明 <- 小强 : 明天没时间.
小明 -> 小强 : 收到!

2.4 重发超时机制 (提高可靠性)

刚刚的情况可能会发生丢包的情况: ① 发送端丢包 ② 确认应答丢包
重发超时就是指 在重发数据之前,等待确认应答到来的那个特定时间间隔.如果超过了这个时间间隔还未收到确认应答就会进行数据重发.

但是数据也不会被无限的重发,达到了一定的次数之后,如果仍然没有有任何确认应答,就会判断网络或者对端主机发生了异常,强制关闭连接.
例如: 丢包的概率位 10%
第一次丢包 10%
第二次丢包 10% * 10% = 1%
第三次丢包 10% * 10% * 10% = 0.1%
丢包次数太多,概率太小,就是别的问题了.

2.5 连接管理:

可以使用TCP首部用于控制的字段来管理TCP连接. 一个连接的建立与断开,正常过程至少需要来回发送7个包才能完成(三次握手,四次挥手).

TCP 三次握手

TCP 四次挥手

2.6 滑动窗口 (提高效率)

为了解决(TCP以一个段位单位发送.这样的通信性能就大大降低了.)这个问题,引入了窗口.

  • 窗口的大小指的是无需等待确认应答而可以继续发送数据的最大值.
  • 上图的窗口大小是 4 个段
  • 操作系统内核为了维护这个滑动窗口,需要开辟 发送缓冲区 来记录当前还有哪些数据没有
    应答;只有确认应答过的数据,才能从缓冲区删掉;

情况1: 数据包到达,ACK丢了

在这种情况下,数据已经到达了对端,此时就不需要再进行重发.如图

这里看出就算丢了1001的ACK,2001的ACK,后面收到了3001的ACK的时候,也会知道收到了数据,就不会受影响.

情况 2: 数据包丢了

如果发送端主机如果连续3次收到同一个确认应答,就会将其所对应的数据进行重发.这种机制比超时管理更高效,称为高速重发控制

2.7 流量控制 (提高可靠性)

接收端处理数据的速度是有限的。如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发
送端继续发送,就会造成丢包,继而引起丢包重传等等一系列连锁反应。
为了防止这种现象,TCP提供了一种机制可以让发送端根据接收端的实际接收能力控制发送的数据量。这就是流量控制。

2.8 拥塞控制(提高可靠性)

在网络出现拥堵时,如果突然发送一个较大量的数据,极有可能会导致整个网络的瘫痪。
TCP为了防止这个问题,在通信一开始就会通过一个叫作 慢启动 的算法得出的数值,对发送数据量进行控制。

当网络通畅时,就逐渐加大发送速率
当网络出现丢包的时候,就立即降低发送速率

  • 此处引入一个概念程为拥塞窗口
  • 发送开始的时候,定义拥塞窗口大小为1;
  • 每次收到一个ACK应答,拥塞窗口加1;
  • 每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口大小做比较,取较小的值作为实际发送的窗口 真实窗口大小 = min(流量窗口,拥塞窗口)

  • 当TCP开始启动的时候,慢启动阈值等于窗口最大值;
  • 在每次超时重发的时候,慢启动阈值会变成原来的一半,同时拥塞窗口置回1;

2.9 延时应答 (提高效率)

接收数据的主机如果每次都立刻回复确认应答的话,可能会返回一个较小的窗口.那是因为刚接收完数据,缓冲区已满.

当某个接收端收到这个小窗口的通知以后,会以它为上限发送数据,从而又降低了网络的利用率,
为此引入了一个方法,那就是收到数据后并不立即返回确认应答,而是延迟一段时间的机制.

TCP文件传输中,绝大多数是每两个数据段返回一次确认应答

2.10 捎带应答 (提高效率)

在延迟应答的基础上,我们发现,很多情况下,客户端服务器在应用层也是 “一发一收” 的。意味着客户端给服务器说了 “How are you”,服务器也会给客户端回一个 “Fine, thank you”;
那么这个时候ACK就可以搭顺风车,和服务器回应的 “Fine,thank you” 一起回给客户端

在通信中,TCP的确认应答和回执数据可以通过一个包发送.

由于这种情况,四次挥手有可能会变成三次,

2.11 面向字节流 (粘包问题)

解决粘包问题的方法:

1. 给应用层数据设定 “结束符” / “分隔符”

2. 给应用层数据设定 “长度”

2.12 异常情况 (心跳机制)

1. 进程终止

进程终止会释放文件描述符,仍然可以发送FIN。和正常关闭没有什么区别

2. 机器重启

和进程终止的情况相同.(可能四次挥手没有挥完)

3. 机器掉电/网线断开

  1. 掉电的是接收方,
    此时发送方还在发送数据,此时显然会触发超时重传,重传几次之后,就会尝试重置连接,
    然后发送方就会放弃这个连接,把连接对应的资源回收了
  2. 掉电的是发送方,
    此时另外一方在尝试接收数据,此时收不到任何数据,此时采取"心跳包"机制.
    每隔一段时间,向对方发送一个 PING 包,期待对方返回一个 PONG 包~
    如果 PING 包发送过去了,过了很久还没 PONG,并且重试几次也不行,此时就认为对方挂了.

3. 面试常考题

1. 如何基于UDP协议实现可靠传输?

  1. 实现确认应答机制. 每个数据收到之后,都要反馈一个ACK(应用程序自己定义一个 ack包)
  2. 实现序号/确认序号,以及实现去重
  3. 实现超时重传.
  4. 实现连接管理
  5. 要想提高效率,实现滑动窗口
  6. 为了限制滑动窗口,实现流量控制/拥塞控制
  7. 实现延时应答,捎带应答,心跳机制…

2. 啥样的场景中适合使用TCP,啥样的场景中适合使用UDP

  1. 如果需要可靠性-> 首选 TCP
  2. 如果传输的单个数据报比较长(超过 64k) -> 首选 TCP
  3. 如果特别注重效率 -> 优先考虑 UDP
  4. 如果需要广播-> 优先考虑 UDP

相关文章