- 「计算机网络笔记」第一章 概述
- 「计算机网络笔记」第二章 物理层
- 「计算机网络笔记」第三章 网络层
- 「计算机网络笔记」第四章 介质访问控制子层
- 「计算机网络笔记」第五章 网络层
- 「计算机网络笔记」第六章 传输层
- 「计算机网络笔记」第七章 应用层
6.1 传输层概述
网络层主要运行在路由器上,因此用户无法真正控制的到网络层
传输层标准同一的原语,即可使用网络服务
-
传输层服务和网络层服务的不同
- 网络层负责把数据从源机送达至目的机
- 传输层负责把数据送达到具体的
应用进程
PDU:
数据段
(TPDU/Segment)-
传输层的协议
- UPD:用户数据报协议
User Datagram Protocol
- 面向无连接型
- TCP:传输控制协议
Transmission Control Protocol
- 面向有连接型
- UPD:用户数据报协议
6.2 用户数据报协议 UDP
User Datagram Protocol
- 是传输层上一个轻量级的协议,提供高效的
端到端
的数据段
传输 - UDP不提供数据传输的可靠保证
-
一对多
的使用场景必须使用UDP
UDP数据段头
- 字段:每段2Byte
- 源端口
Source Port
- 目的端口
Destination Port
- UDP Length
- UDP Checksum
- 源端口
端口号 | |
---|---|
0 ~ 1023 | 公共应用,INAN分配(知名端口) |
1024 ~ 49151 | 用户端口,注册端口 |
49152 ~ 65535 | 动态端口,私人端口 |
例如:访问网站时
网站的端口号通常为知名端口,如:80
自己的端口号为自由端口,通常为操作系统随机分配的>49151的端口号
6.3 通信模型
-
端点
- 套接字
Socket
- (IP,Port)
- 套接字
-
通信三元组
- (源端,目的端,传输协议)
地址 | 作用 |
---|---|
MAC地址 | 识别同一链路中不同的计算机 |
IP地址 | 识别TCP/IP网络中互连的主机和路由器 |
端口号 | 识别同一台计算机中进行通信的不同应用程序 |
端口号也称程序地址
6.4 TCP数据段
TCP实体
- 管理TCP流和IP层的
接口
- 亦可以是
用户进程
或操作系统内核
TCP段头
- 源端口、目的端口
- 序列号:为每个字节编号
- 确认号(32bit)
- 期望接收的序列号
-
ack控制位
置位才有效 - TCP可靠传输的保证:
肯定确认机制
- 六个控制位(1bit):用于建立连接、拆除、异常处理等
- 窗口尺寸:用于流控
Flow Control
,以免收方被数据淹没
控制位
- URG
Urgent Flag
- 标明紧急数据的起始位置
- 收方收到,首先处理
- ACK
Acknowlegement Flag
- 1:启用捎带确认
- 0:确认号是无效的
- PSH
Push Flag
- 收方收到后,应立刻送往上层,而不需要缓存它
- RST
Reset Flag
- 重置一个已经非常混乱的连接
- 如果处于连接建立阶段,直接拒绝建立该连接
- SYN
Synchronize Flag
- (SYN=1,ACK=0):连接建立请求
- (SYN=1,ACK=1):连接接收
- FIN
Fin Flag
- 释放连接
- 发送方已无数据需要发送,但可以继续接收数据
6.5 TCP三次握手建立连接
- 任何采用了TCP的应用,都会在正式传输数据前,搭建此TCP的连接
- 三次握手,也称
同步
- 握手的过程中,双方交换
初始序列号
- 全双工:双方可以互相收发数据
建立连接的过程
- 一方
Server
被动地等待一个进来的连接请求 - 另一方
Client
通过发送连接请求,设置参数 - 服务器方回发确认应答
- 应答到达请求方,请求方最后确认,连接建立
- 第一次握手:Client -> Server
- 连接请求数据段
SYN
- SYN(SEQ = x)
-
x
为初始序列号,Client随机产生 - 控制位:SYN=1,ACK=0
- 连接请求数据段
- 第二次握手:Client <- Server
- 连接应答
SYN
- SYN(SEQ = y,ACK = x+1)
-
y
为初始序列号,Server随机产生 -
ACK = x+1
表示对Client的 x 号字节的确认 - 控制位:SYN=1,ACK=1
- 连接应答
- 第三次握手:Client -> Server
- 最后的确认
- (SEQ = y+1,ACK = x+1)
- 控制位:SYN=0,ACK=1
拒绝服务攻击 DoS
攻击人Attacker控制一些机器,装有Agent
Agent向被攻击的服务器Victim不断发送第一次握手信息,其中包含了一个伪造且不存在的源IP地址
服务器Victim处理这些Agent发送的握手,回发第二次握手信息,并等待第三次握手信息
但因为第一次握手信息中的源IP是不存在的,所有服务器Victim根本就收不到第三次握手信息
服务器Victim被挂起太多等待的进程,最终资源耗尽而瘫痪
6.6 TCP连接释放
TCP是全双工,连接的释放必须是双向的
任何一方在没有数据要发送时,都可以发送一个
FIN
置位了的TCP数据段当
FIN
被确认的时候,该方向的连接被关闭当双向连接都关闭,连接释放
释放的流程
将释放连接
的决定权交给请求者独立裁定
-
发送方发送
连接释放请求DR
(Disconnect Request),且期待对方的确认ACK
- 当DR到达接收端,接收端回发
ACK
,并且也发送一个DR
- 当接收端的ACK到达发送端的时候,连接释放(发送端->接收端),同时回发
确认ACK
- 当发送端的ACK到达接收端的时候,反方向的连接(接收端->发送端)也释放了
DR和ACK丢失的问题
- 采用
定时器
- 任何时候,发送DR的同时,为其启动一个定时器
- 如果一方发送了
FIN
置位了的DR数据段出去,却在定时器超期之后都没有收到应答,释放
此方向的连接 - 另一方最终会注意到对面已经不在了,超时后连接释放
- 定时器
超期
时,强制释放连接(避免下文提到的半开放连接) - 以上应该为接收方收到初始DR,回传的ACK丢失
初始的DR和重传都丢失的问题
发送者将因超时放弃发送且
释放连接
但另一方因为最初的DR请求都没有收到,仍然处于
活跃状态
以上情况为,半开放连接
half-open
6.7 TCP传输策略
举例
Receiver有个空的4k大小的Buffer区
Sender发送了一个2k大小的,第一个SEQ = 0的数据(SEQ ∈ 0~2047)
Receiver的Buffer区被占用一半,回发ACK = 2048,WIN = 2048,表示
- Sender发送的数据从0 ~ 2047都被接收,下一次可以从SEQ = 2048开始发送
- 且通过WIN = 2048,通知Sender,这里只有2k大小的空间
Sender收到Receiver的ACK后,再次发送了2k大小的,第一个SEQ = 2048的数据
Receiver收到后,Buffer被完全充满,回发ACK = 4096,WIN = 0,表示
- 没有剩余空间接收新的数据了
当一段时间后,Receiver处理了部分Buffer的数据,回发ACK = 4096,WIN = 2048
Sender收到Receiver的ACK后,重新开始发送数据... ...
- 当窗口数为
0
时,发送者不能正常发送数据段 - 特殊情况:
Urgent
数据- 如,用户想 Kill 远端机器上的进程
- 发送者可以发送一个字节的数据段,以便让接收者再次发送
ACK
和WIN
避免死锁
6.8 TCP拥塞控制
引发拥塞的因素
-
接收方
处理不过来 => 窗口尺寸量度 -
通信子网
中出现拥塞 => 拥塞窗口量度
拥塞控制的三个参数
- 接收端窗口/窗口尺寸(WIN)
- 拥塞窗口
- 阈值
拥塞的解决
- 分组守恒原则:一个老的分组离开后,才允许新的分组注入网络
- TCP实体
动态维护
一个的窗口大小 - 窗口大小/发送的字节数 = MIN(接收者窗口,拥塞窗口)
慢启动算法 Slow Start
- 当连接建立的时候,发送者用当前使用的
最大数据段长度
初始化拥塞窗口
,然后发送一个最大数据段 - 如果在定时器超期之前收到确认,则
拥塞窗口
翻倍,然后发送两个数据段 - 循环往复,指数增长,直至超时/或达到
接收窗口
的大小 - 拥塞窗口增长到
阈值
时,按照<u>线性增长</u>(线性增加一个最大数据段长度)
例如:
如果试图发送4096字节没有引发超时,但是发送8192字节的时候,超时没有收到确认
则拥塞窗口设为4096字节
阈值
初始化为64k- 当超时发生的时候
- 阈值降为当前拥塞窗口的
一半
- 同时将拥塞窗口
重设
为一个最大数据段的长度,重新开启慢启动
- 快速恢复:
重启慢启动
算法时,拥塞窗口值直接设置为阈值的大小(降低后的),直接开始线性增长
- 阈值降为当前拥塞窗口的
控制
- 慢启动算法和阈值相互配合,不断超时,不断重启,尝试出的拥塞窗口的值,也随着
网络状况
的变化发生变化,<u>达到拥塞控制的目的</u> - TCP传输实体收到
ICMP抑制分组
,则当前事件作超时
6.9 TCP定时器
死锁的场景
- 接收方发送了一个
WIN=0
的确认(窗口更新),告诉发送方等待 - 当接收方的缓冲区空出空间,发送
更新窗口
的数据段,然而,该分组丢失 - 因此,收发双方都在等待对方发送数据段,但永远等不到,产生死锁
持续定时器
- 用于解决上述的死锁问题
- 在发送方收到
WIN=0
时,启动一个持续定时器
- 定时器超期都没有收到
更新窗口
,则发送一个探测数据段
,引发对方重新发出更新窗口 - 探测数据段:哑的TCP数据段
Dump TCP Segment
保活定时器
- 用来检查连接是否存活
- 当一个连接空闲的时间超过保活定时器的时间,该连接将被杀掉