少女祈祷中...

UDP

1、介绍
UDP是一个简单的面向数据报的协议:进程的每个输出操作都刚好产生一个UDP数据报,并被组装成一份待发送的IP数据报。 在此同时也解析一下TCP的面向数据流: 应用程序产生的全体数据和真实发生的单个IP数据报
之间可能没有什么联系,即一个应用程序数据包有可能被分成多个IP数据报或者和另外一个应用程序数据报的一部分组装成一个IP数据报一起发送(大了会被拆,小了就充组装)因为这个原因,TCP就会出现粘包的现象。
由于这个UDP的数据报可能非常长,以至于超过了网络的MTU,因此就会涉及到IP分片(可以说IP分片主要就是为UDP服务的)。
UDP 是不可靠的协议,只负责将数据报发送出去,并不保证数据能够到达目的地。
UDP首部结构

  • 端口号表示发送的进程和结束的进程。
  • TCP和UDP的端口号是相互独立的。
  • UDP长度,首部+数据的长度。
  • UDP校验和,通过对UDP首部,数据部分,伪首部(包括源目IP地址、协议、长度等一些字段,目的是为了让UDP两次检查数据是否已经正确到达目的地)一起状一个校验和得到的值。
    UDP的最大数据报长度理论上是IP最大数据报长度减去IP首部的长度,但是实际上还是和应用程序的接收现在有关。
    2、UDP的三大运用
  • 查询类,例如DNS
  • 实时流量,如语音 视频
  • 传输数据,如TFTP,主要用于在资源有限的设备搭建TFTP服务器,来传输文件,升级系统

广播和多播(组播)

广播和多播仅应用于UDP,TCP一定是单播,肯定不能多播和组播。
多播是在设备驱动程序层被过滤的:如果网卡未订阅该多播,则直接在硬件层面丢弃,不会上传到网络层。
广播能一直传到传输层UDP处,检查目标端口是否有应用监听,若无监听就丢弃。
1、广播
广播地址受限广播:255.255.255.255(仅本地网络)子网定向广播:192.168.1.255(特定子网)
处理流程:
- 网卡层:必须接收MAC广播帧(FF:FF:FF:FF:FF:FF)
- IP层:校验目标IP是否为有效广播地址
- 传输层:UDP:提交给绑定端口的应用;TCP:直接拒绝(违反连接语义)
2、多播
多播组地址:最高4bit位是1110的D类地址,范围是224.0.0.0 ~239.255.255.255。多播的MAC地址是01:00:5e:00:00:00 ~ 01:00:5e:7f:ff:ff。IP地址到mac地址的映射不是唯一的,因此会出现多个
IP地址对于一个MAC地址,所以设备驱动程序或IP层就必须对数据报进行过滤,以避免接收到主机不想接收的多播数据帧
处理流程:
- 网卡层:基于IGMP/MLD维护的多播MAC列表过滤;硬件级过滤未订阅的组播帧(优化性能)
- IP层:校验目标IP是否在已加入的多播组
- 传输层:检查是否有应用绑定多播IP+端口

DNS

1、简介
域名系统,是一种用于TCP/IP应用程序的分布式数据库,提供主机名到IP地址之间的转换和电子邮件的选路信息。对DNS的访问是通过一个地址解析器来完成的(windows上可以用nsloookup来查看),解析器通常是
应用程序的一部分,并不涉及到操作系统的内核。
DNS 的名字空间和UNIx的文件系统类似,具有层次结构/树结构。命名标识不区分大小写,命名树上任何一个节点的域名就是将该节点到最高层的域名串连起来中间使用‘.’来分割这些域名。
DNS树形结构
2、 报文格式
DNS报文格式

  • 标识,有客户程序设置并由服务器返回结果。客户程序通过它来缺点响应哈查询是否匹配。
  • 16bit标志字段被划分成若干字段:
    • QR 1bit,0表示查询报文,1表示响应报文。
    • opcode 4bit,通常值:0标准查询,1反向查询,2服务器状态请求。
    • AA 1bit,表示授权回答。
    • TC 1bit,表示截断的。DNS只能会512字节,大于了512就会被截断
    • RD 1bit,表示期望递归。
    • RA 1bit,表示可以递归。
    • zero 3bit,保留位,必须为0.
    • rcode 4bit返回码字段,响应码(0=无错误,2=服务器失败,3=域名不存在,4=查询类型不支持)。
  • 问题部分:
    • QNAME 域名(可变长度,格式如 3www7example3com0,以 0 结束)
    • QTYPE 查询类型(2 字节,如 A=1、AAAA=28、MX=15、CNAME=5)
    • QCLASS 查询类(通常为 1,表示 Internet(IN))
  • 回答部分:
    • NAME 域名(可能使用压缩指针,如 0xC00C 指向报文中的已有域名)
    • TYPE 记录类型(同 QTYPE)
    • CLASS 记录类(同 QCLASS)
    • TTL 生存时间(4 字节,单位秒,控制缓存有效期)
    • RDLENGTH 数据长度(2 字节)
    • RDATA 记录数据(可变长度,如 A 记录为 4 字节 IPv4 地址)
      3、工作流程
      以访问www.baidu.com为例。
  • 客户端发起查询:用户在浏览器输入 www.baidu.com ;操作系统检测本地DNS缓存;如果无缓存,则向配置的 递归解析器(如8.8.8.8)发送DNS请求。
  • 递归解析器处理:查看自身DNS缓存;若无缓存,开始迭代查询。
    -结果返回与缓存:递归解析器将 IP 地址返回给客户端,并缓存结果(根据记录的 TTL 值)。客户端收到 IP 地址,建立 TCP 连接访问网站。

TFTP

1、介绍
TFTP是一种基于 UDP/69 端口 的轻量级文件传输协议,常用于网络设备固件更新、无盘工作站启动等场景。其报文结构简单,分为 5 种类型,每种类型有固定格式。
主要是停止等待协议,发一个数据报,就要等待接收到确认后再发第二个包。
2、TFTP报文格式
TFTP报文格式

  • 操作码:
    • 1 RRQ,客户端 → 服务器 读请求(下载文件)
    • 2 WRQ,客户端 → 服务器 写请求(上传文件)
    • 3 DATA,双向 数据块传输
    • 4 ACK,双向 确认接收
    • 5 ERROR,双向 错误通知
  • Opcode = 1/2 RRQ/WRQ(读/写请求)时:
    • Filename:请求传输的文件名(以 0x00 结尾)。
    • Mode:传输模式(字符串,以 0x00 结尾):netascii:文本模式(ASCII 转换);octet:二进制模式(原始字节流)。
  • Opcode = 3 DATA(数据块):
    • Block #:数据块编号(从 1 开始递增)。
    • Data:文件数据(最大 512 字节)。如果数据 <512 字节:表示文件传输结束。
  • Opcode = 4 确认
    • Block #:确认的数据块编号(与 DATA 的 Block # 对应)。
  • Opcode = 5 错误:
    • Error Code:错误码。0 未定义错误;1 文件未找到;2 访问权限拒绝;3 磁盘已满;4 非法操作(如不支持 WRQ);5 未知传输ID(端口号错误);6 文件已存在(WRQ 冲突);7 无此用户(已废弃)
    • ErrMsg:人类可读的错误描述(以 0x00 结尾)。
      3、TFTP工作流程简介
      文件下载流程:
  • 客户端发起读请求(RRQ)-》服务器响应数据块(DATA)-》客户端确认接收(ACK)-》循环传输直至完成
    文件上传流程:
  • 客户端发起写请求(WRQ)-》服务器响应初始ACK(Block #=0)-》客户端发送数据块(DATA)-》服务器确认接收(ACK)-》循环传输直至完成

TCP

1、介绍
TCP提供一种面向连接的、可靠的字节流服务,这意味着两个使用TCP的应用在交换数据之前必须先建立一个TCP连接,且在一个TCP连接中仅有两方进行通信,不存在广播和多播。
TCP通过以下方式来提供可靠性:
- 应用数据会被封给成TCP认为合适的数据库大小(MSS)
- 当TCP发送出一个段后,会启用一个定时器,等待目的端确认收到这个报文段,如果没有及时收到确认,则重发报文段
- 当TCP收到另外一端的数据,可以不立马发送确认,可以等一会儿再发(取决于滑动窗口大小),确认ACK也可以跟着数据一起发送回去–捎带确认
- TCP包到达目的端会失序,因此接收端会对收到的数据重新排序后发送给上层应用

2、TCP报文格式
TCP报文格式

  • 源目端口号用于寻找发送端和接收端的应用程序,这两个值加上IP首部的源目IP地址可以确定唯一一个TCP连接
  • 序号,用于标识发送的数据字节流,表示在这个报文段中的第一个数据字节。没发送完x个字节的数据,序号都会+x+1,即使没有数据,SYN/FIN包也会消耗一个序号
  • 确认序号,为上次已经收到的数据字节序号+1,重要ACK标记时,确认序号才有效
  • 六个标准位:URG-紧急指针 ACK-确认序号有效 PSH-接收方应该尽快将报文段交给应用层 RST-重建连接 SYN-同步序号发起一个连接 FIN-完成发送任务,请求断开连接。
    TCP为应用层提供全双工服务,数据能够在两个方向独立的传输,因此每一端都必须保持每个方向上的传输数据序号。

3、三次握手/四次挥手

  • 三次握手(SYN, SYN+ACK, ACK)
    Client Server
    |—-SYN(seq=x)—–>|
    |<—SYN(seq=y),ACK–|
    |—-ACK(seq=x+1)—>|
    客户端调用 connect()|服务端调用 accept(),进入 SYN_RCVD|双方建立连接,进入 ESTABLISHED
  • 四次挥手
    Client Server
    |—-FIN(x)—>|
    |<—ACK(x+1)–|
    |<—FIN(y)—-|
    |—-ACK(y+1)->|
    被动关闭方在收到 FIN 后进入 CLOSE_WAIT|主动关闭方最终进入 TIME_WAIT

4、流量控制与拥塞控制

  • 流量控制(基于接收端通告窗口 rcv_wnd),防止发送方过快发送,接收方来不及处理:每次 ACK 都会更新窗口大小
  • 拥塞控制(基于网络拥堵状态):慢启动(Slow Start);拥塞避免(Congestion Avoidance);快重传 & 快恢复(Fast Retransmit/Recovery)
    现在有 拥塞窗口:cwnd 接收端通告窗口:rwnd 慢启动门限:ssthresh
    • 对于一个连接刚开始时 cwnd 设置为 1MSS ssthresh 设置为 65535字节。然后接收端每次收到一个ACK时都会将cwnd 翻倍
    • TCP 输出的报文数量不能超过 cwnd和rwnd的最小值
    • 当网络发生拥塞时(收到1重复确认或者丢包时),就将 ssthresh 设置为当前 cwnd 大小的一般,然后cwnd重新设置为 1(这就是慢启动),
      然后在cwnd小于 ssthresh 时,就以每收到一个ACK翻倍增加;大于 ssthresh时,每收到一个ACK时,增加 ssthresh 的一半 (拥塞避免-超时重传
      快重传,收到3个连续的ACK就重传对应的包。
      快恢复,快重传后就继续进行拥塞避免算法而不是慢启动(快重传并不是网络不好,如果执行慢启动就比较浪费资源)

5、状态机与定时器

  • 状态转移图(RFC 793)
    server:
    LISTEN(等待连接请求) → SYN_RCVD(接收 SYN 后,回应 SYN+ACK) → ESTABLISHED(连接建立,数据传输阶段) → CLOSE_WAIT(被动关闭一方收到 FIN 后进入,准备关闭连接)
    → LAST_ACK(被动关闭方发送 FIN 后等待对方 ACK) → CLOSED(连接已关闭)
    client:
    SYN_SENT(发送了连接请求SYN) → ESTABLISHED(连接建立,数据传输阶段) → FIN_WAIT_1 → FIN_WAIT_2 → TIME_WAIT(主动关闭方收到对方 FIN 后进入,等待 2MSL 时间) → CLOSED
    FIN_WAIT_1 / 2:主动关闭连接后的两个中间状态。

  • 四种定时器
    重传定时器(Retransmission):超时重传未被确认的数据包。每次发送数据段时启动此定时器,如果超时还未收到 ACK,就触发重传,超时时间通过RTT动态计算。
    保活定时器(Keepalive):检测连接是否存活。长时间没有数据交换时,发送一个“保活探测包”。若对方无响应,重发探测最多 n 次(例如 BSD 中为 8 次),超出次数则关闭连接。
    2MSL定时器(Time-Wait):确保连接中延迟的报文完全消失。2MSL = 2 × 最大报文生存时间(MSL,一般为 30s~2min)。TCP 连接进入 TIME_WAIT 状态后,保持 2MSL 时长,再彻底关闭连接。 防止“旧连接包”干扰新的连接。
    持续定时器(Persist): 避免接收窗口为0时发生死锁。 如果接收方通告窗口为 0,发送方停止发送数据,并启动 Persist Timer。该定时器触发时,发送窗口探测报文,试探接收方是否恢复了窗口。