Linux网络——传输层协议

所谓传输层,即负责数据能够从发送端传输到接收端。

在 TCP/IP 协议中, 用 "源 IP", "源端口号", "目的 IP", "目的端口号", "协议号" 这样一个五元组来标识一个通信(可以通过 netstat -n 查看)。


一.UDP协议

1.协议端格式

16 位 UDP 长度, 表示**整个数据报(UDP 首部+UDP 数据)**的最大长度;

如果校验和出错, 就会直接丢弃。


2.特点

UDP 传输的过程类似于寄信。

  • 无连接: 知道对端的 IP 和端口号就直接进行传输, 不需要建立连接;
  • 不可靠: 没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方,UDP 协议层也不会给应用层返回任何错误信息;
  • 面向数据报: 不能够灵活的控制读写数据的次数和数量。

3.面向数据报

应用层交给 UDP 多长的报文, UDP 原样发送, 既不会拆分, 也不会合并;

假如用 UDP 传输 100 个字节的数据:

如果发送端调用一次 sendto, 发送 100 个字节, 那么接收端也必须调用对应的一次 recvfrom, 接收 100 个字节; 而不能循环调用 10 次 recvfrom, 每次接收 10 个字节;

UDP 协议首部中有一个 16 位的最大长度. 也就是说一个 UDP 能传输的数据最大长度是 64K(包含 UDP 首部)。

然而 64K 在当今的互联网环境下, 是一个非常小的数字。如果我们需要传输的数据超过 64K, 就需要在应用层手动的分包, 多次发送, 并在接收端手动拼装。


二.TCP协议

TCP 全称为 "传输控制协议(Transmission Control Protocol"). 如其名, 要对数据的传输进行一个详细的控制。


1.协议端格式

TCP报头包含上述除数据外的全部部分。

TCP的标准报头为20字节 ,不包含选项字段,但是4位首部长度(单位4字节)则表示整个报头的字节数,所以TCP报头的最大长度为60字节,包含选项字段。因此选项字段所占字节数,即为4位首部长度表示的整个报头大小减去20字节。

源/目的端口号: 表示数据是从哪个进程来, 到哪个进程去。

6 位标志位:

  • URG: 紧急指针是否有效
  • ACK: 确认号是否有效
  • PSH: 提示接收端应用程序立刻从 TCP 缓冲区把数据读走
  • RST: 对方要求重新建立连接; 我们把携带 RST 标识的称为复位报文段
  • SYN: 请求建立连接; 我们把携带 SYN 标识的称为同步报文段
  • FIN: 通知对方, 本端要关闭了, 我们称携带 FIN 标识的为结束报文段

2.确认应答(ACK)机制

TCP 将每个字节的数据都进行了编号,即为序列号

发送方发送数据后,只有在收到接收方的确认应答之后,才会继续发送,每一个 ACK 都带有对应的确认序列号, 意思是告诉发送者, 我已经收到了哪些数据; 下一次你从哪里开始发。


3.超时重传机制

主机 A 发送数据给 B 之后, 可能因为网络拥堵等原因, 数据无法到达主机 B;

如果主机 A 在一个特定时间间隔内没有收到 B 发来的确认应答, 就会进行重发;

但是, 主机 A 未收到 B 发来的确认应答, 也可能是因为ACK 丢失了,因此主机 B 会收到很多重复数据. 那么 TCP 协议需要能够识别出那些包是重复的包, 并且把重复的丢弃掉. 这时候我们可以利用前面提到的序列号, 就可以很容易做到去重的效果。

超时时间一般由OS自主设定,如果累计到一定的重传次数后,仍然没有收到应答,TCP 认为网络或者对端主机出现异常, 强制关闭连接。


4.连接管理机制

在正常情况下, TCP 要经过三次握手建立连接, 四次挥手断开连接。


(1)三次握手

三次握手,即客户端向服务器发起连接请求,服务器应答的同时,也向客户端发起连接请求,最终由客户端发送最终应答,这样便可以完整的建立连接。

为什么要三次握手:

  1. 验证全双工,验证网络连通性。
  2. 建立通信双方的共识意愿。

(2)四次挥手

四次挥手,即通信双方要断开连接时,都必须向对方发送断开申请,并且都得到应答之后,才能彻底的断开连接。

TIME_WAIT状态:

TCP 协议规定,主动关闭连接的一方要处于 TIME_ WAIT 状态,等待两个MSL(maximum segment lifetime)(TCP报文的最大生存时间)的时间后才能回到 CLOSED 状态。

CLOSE_WAIT状态:

服务器没有正确的关闭socket,导致四次挥手没有正确完成。这是一个 BUG,只需要将socket进行 close 即可解决问题。


5.流量控制

接收端处理数据的速度是有限的. 如果发送端发的太快, 导致接收端的缓冲区被打满, 这个时候如果发送端继续发送, 就会造成丢包, 继而引起丢包重传等等一系列连锁反应。

因此 TCP 支持根据接收端的处理能力, 来决定发送端的发送速度. 这个机制就叫做流量控制(Flow Control);

  • 接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 "窗口大小" 字段, 通过 ACK 端通知发送端。
  • 窗口大小字段越大, 说明网络的吞吐量越高。
  • 接收端一旦发现自己的缓冲区快满了, 就会将窗口大小设置成一个更小的值通知给发送端。
  • 发送端接受到这个窗口之后, 就会减慢自己的发送速度。
  • 如果接收端缓冲区满了, 就会将窗口置为 0; 这时发送方不再发送数据, 但是需要定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端。

通信双方在三次握手建立连接时,就已经通过16位窗口大小协商好双方的接收能力了。

如果接收方迟迟不能读取数据,则可以设置六位标记位中的PSH ,提示接收端应用程序立刻从 TCP 缓冲区把数据读走。

同时也可以设置URG 标记位,设置紧急指针,指向需要紧急处理的数据的最后一个字节位置,表示该段数据应该尽快被上层获取。


6.滑动窗口

在前边分享的应答机制中,每发送一次数据,就要收到一个ACK应答,然后再发送下一段数据,这样做有一个比较大的缺点, 就是性能较差. 尤其是数据往返的时间较长的时候。

同时还联系到流量控制 中未提及的问题:发送方是如何根据对方的接收能力来发送数据的?

既然这样一发一收的方式性能较低, 那么我们一次发送多条数据 , 就可以大大的提高性能(其实是将多个段的等待时间重叠在一起了),这种方式就是滑动窗口

发送方规定滑动窗口的概念,在滑动窗口以内的数据,可以直接发送而无需等待收到应答。

发送前四个段的时候, 不需要等待任何 ACK, 直接发送; 收到第一个 ACK 后, 滑动窗口向后移动, 继续发送第五个段的数据; 依次类推。

滑动窗口的大小是多少呢?对方同步过来的16位窗口大小,就是滑动窗口的大小

这意味着滑动窗口的大小是可以改变的,同时滑动窗口只能向右移动。


那么如果采用滑动窗口的方式,在发送过程中发生了丢包,该怎么办呢?

(1)数据丢包

首先我们要知道的是当收到确认序号时,代表着确认序号之前的数据收到了 ,下一个要接收确认序号之后的数据,如果一直重复发送某个确认序号,就说明该确认序号后的一段数据丢包了

比如说1001-2000的数据丢失了,那么接收方就会一直发送1001ACK,因为其没有收到1001,如果发送端主机连续三次收到了同样一个 "1001" 这样的应答, 就会将对应的数据 1001 - 2000 重新发送。

这个时候接收端收到了 1001 之后, 再次返回的 ACK 就是 7001 了(因为 2001 - 7000)接收端其实之前就已经收到了, 被放到了接收端操作系统内核的接收缓冲区中,这种机制被称为 "高速重发控制 "(也叫 "快重传 ")。


(2)应答丢包

如果只是部分ACK丢包了,其实无关紧要,因为只要能够收到后续的ACK,就说明前边的数据接收方也一定接收到了。


7.拥塞控制

虽然 TCP 有了滑动窗口能够高效可靠的发送大量的数据. 但是如果在刚开始阶段就发送大量的数据, 仍然可能引发问题.

因为网络上有很多的计算机, 可能当前的网络状态就已经比较拥堵. 在不清楚当前网络状态下, 贸然发送大量的数据, 是很有可能引起雪上加霜的.

TCP 引入 慢启动机制, 先发少量的数据, 探探路, 摸清当前的网络拥堵状态, 再决定按照多大的速度传输数据。

此处引入概念拥塞窗口:

  • 发送开始的时候, 定义拥塞窗口大小为 1;
  • 每次收到一个 ACK 应答, 拥塞窗口加 1;
  • 每次发送数据包的时候, 将拥塞窗口和接收端主机反馈的窗口大小做比较, 取较小的值作为实际发送的窗口;

像上面这样的拥塞窗口增长速度, 是指数级别的. "慢启动" 只是指初使时慢, 但是增长速度非常快.

  • 为了不增长的那么快, 因此不能使拥塞窗口单纯的加倍。
  • 此处引入一个叫做慢启动的阈值。
  • 当拥塞窗口超过这个阈值的时候, 不再按照指数方式增长, 而是按照线性方式增长。
  • 当 TCP 开始启动的时候, 慢启动阈值等于窗口最大值;
  • 在每次超时重发的时候, 慢启动阈值会变成原来的一半, 同时拥塞窗口置回 1;
  • 少量的丢包, 我们仅仅是触发超时重传; 大量的丢包, 我们就认为网络拥塞;
  • 当 TCP 通信开始后, 网络吞吐量会逐渐上升; 随着网络发生拥堵, 吞吐量会立刻下降;
  • 拥塞控制, 归根结底是 TCP 协议想尽可能快的把数据传输给对方, 但是又要避免给网络造成太大压力的折中方案。

三.TCPvsUDP

我们说了 TCP 是可靠连接, 那么是不是 TCP 一定就优于 UDP 呢? TCP 和 UDP 之间的优点和缺点, 不能简单、绝对的进行比较:

  • TCP 用于可靠传输的情况, 应用于文件传输, 重要状态更新等场景;
  • UDP 用于对高速传输和实时性要求较高的通信领域, 例如, 早期的 QQ, 视频传输等. 另外 UDP 可以用于广播;

归根结底, TCP 和 UDP 都是程序员的工具, 什么时机用, 具体怎么用, 还是要根据具体的需求场景去判定。

相关推荐
maosheng114617 分钟前
RHCSA的第一次作业
linux·运维·服务器
wifi chicken1 小时前
Linux 端口扫描及拓展
linux·端口扫描·网络攻击
旺仔.2911 小时前
Linux 信号详解
linux·运维·网络
放飞梦想C1 小时前
CPU Cache
linux·cache
Hoshino.412 小时前
基于Linux中的数据库操作——下载与安装(1)
linux·运维·数据库
平生幻2 小时前
TCP协议与UDP协议的区别
网络协议·tcp/ip·udp
播播资源4 小时前
CentOS系统 + 宝塔面板 部署 OpenClaw源码开发版完整教程
linux·运维·centos
源远流长jerry4 小时前
在 Ubuntu 22.04 上配置 Soft-RoCE 并运行 RDMA 测试程序
linux·服务器·网络·tcp/ip·ubuntu·架构·ip
lay_liu4 小时前
Linux安装redis
linux·运维·redis
虾..5 小时前
UDP协议
网络·网络协议·udp