第五章 传输层
传输层提供的服务
- 传输层是只有主机才有的层次,即进程和进程之间的通信,也称端到端通信。
「传输层」功能
传输层的功能
- 传输层提供进程和进程之间的逻辑通信
- 复用和分用
- 传输层对收到的报文进行差错检测
- 传输层的两种协议
- TCP:可靠、面向连接、时延大、适用于大文件
- UDP:不可靠、无连接、时延小、适用于小文件
「传输层」寻址与端口
- 复用:应用层所有的应用进程都可以通过传输层再传输到网络层
- 分用:传输层从网络层收到数据后交付指明的应用进程
- 端口(逻辑端口/软件端口):是传输层的SAP,唯一标识主机中的应用进程
- 端口号只有本地意义,在因特网中不同计算机的相同端口是没有联系的
- 端口号长度为16bit,能表示65536个不同的端口号
- 服务端使用的端口号
- 熟知端口号(0~1023):给TCP/IP最重要的一些应用 程序,所有用户都知道
- 登记端口号(1024~49151):为没有熟知端口号的应用程序使用的,使用时登记
- 客户端使用的端口号(49152~65535):仅在客户进程运行时才动态选择
- 服务端使用的端口号
「传输层」常见端口号
应用程序 | 端口号 |
---|---|
FTP | 21 |
TELNET | 23 |
SMTP | 25 |
DNS | 53 |
TFTP | 69 |
HTTP | 80 |
SNMP | 161 |
「传输层」套接字
- 套接字:主机号+端口号
- 在网络中采用发送方和接收方的套接字组合来识别端点,套接字唯一标识了网络中的一个主机(主机号)和它上面的一个进程(端口号)。
第二节 UDP协议
「UDP协议」UDP数据报
- UDP只在IP数据报服务之上增加了很少功能,即复用分用和差错检测功能。
UDP的主要特点
- UDP是无连接的
- UDP不保证可靠交付
- UDP是面向报文的,适合一次性传输少量数据的网络应用
- UDP无拥塞控制,适合很多实时应用
- UDP首部开销小
面向报文:应用层给UDP多长的报文,UDP就照样发送,即一次发一个完整报文,不做处理
「UDP协议」UDP首部格式
- 首部字段
- 源端口号(16位,2B):可选填,当需要目的主机回应时使用
- 目的端口号(16位,2B):必要,目的进程的端口号
- UDP长度(16位,2B):整个UDP数据报的长度(首部字段+数据字段)
- UDP检验和(16位,2B):检测整个UDP数据报是否有错误
- 数据字段
WARNING
- 分用时,找不到对应的目的端口号,就丢弃报文,并给发送方发送ICMP“端口不可达”差错报告报文
「UDP协议」UDP校验
伪首部
- 伪首部:只有在计算检验和时才出现, 不向下传送也不向上递交
- 伪首部模仿的是IP数据报的首部:
- 源IP、目的IP(4B)
- 0(1B):固定字段
- 17(1B):UDP的协议对应
- UDP长度(2B):UDP首部8B+数据部分长度,不包括伪首部
校验过程
- 若不使用校验,则将校验和字段全部置0
- 发送方
- 加上伪首部
- 全0填充检验和字段
- 全0填充数据部分(使整个UDP数据报是4字节的整数倍)
- 将伪首部+首部+数据字段进行二进制反码求和
- 以16bit(2B)为一组分开进行求和(校验和字段长度)
- 将求和结果填入检验和字段
- 若结果恰好全为0,则全部填入1
- 去掉伪首部
- 发送
- 接收方
- 加上伪首部
- 将伪首部+首部+数据字段进行二进制反码求和
- 结果全为1,则无差错
- 否则视情况丢弃数据,或交给应用层并附上差错警告
第二节 TCP协议
「TCP」TCP协议的特点
- TCP是面向连接(虚连接)的传输层协议
- 只有建立了连接才能开始通信
- 连接是逻辑连接,不是实际链路
- 每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的
- 无法用于广播等
- TCP提供可靠交付的服务,无差错、不丢失、不重复、按序到达
- TCP提供全双工通信
- 发送缓存
- 准备发送的数据
- 已发送但尚未收到确认的数据
- 接收缓存
- 按序到达但尚未被接受应用程序读取的数据
- 不按序到达的数据
- 发送缓存
- TCP面向字节流
- TCP把应用程序交下来的数据看成仅仅是一连串的无结构的字节流
- TCP将要传输的数据分成多个字节,以字节为单位传送
「TCP」报文段的格式
- 源端口、目的端口(16位,2B)
- 序号seq(32位,4B):此报文段中所发送数据的第一个字节的序号
- 在一个TCP连接中传送的字节流中的每一个字节都按顺序编号
- 确认号ack(32位,4B):期望收到对方下一个报文段的第一个数据字节的序号
- 数据偏移(4bit):以4B为单位,表示首部长度,即数据部分从哪里开始
- 控制位(1bit)
- 紧急位URG:为1时,表示该报文中有紧急数据,需要优先从TCP缓存队列中发送
- 确认位ACK:为1时,确认位才有效
- 推送位PSH:为1时,接收方尽快将消息交付到上层,不再等待缓冲区填满后才交付(与URG相对应)
- 复位RST:为1时,表示必须释放连接,然后再重新建立传输链接
- 同步位SYN:为1时,表示这个报文是一个连接建立的请求/接收报文
- 终止位FIN:为1时,表示此报文段发送方数据已发完,要求释放连接
- 窗口(16位,2B):单位为字节(B),表示己方的接收窗口大小,即允许对方发送的数据量(0∼216−10∼216−1)
- 检验和(16位,2B):与UDP类似
- TCP的伪首部代表协议的字段为6
- 紧急指针(16位,2B):URG=1时才有意义,表明本报文中紧急数据的字节数
- 紧急数据从0开始
- 实际上指向的是紧急数据尾部的位置
- 选项(长度可变):最大报文段长度MSS、窗口扩大、时间戳、选择确认
- 填充:使TCP首部长度为4B的整数倍
「TCP」连接管理
TCP连接的建立采用客户服务器方式
- 主动发起连接建立的应用进程叫做客户,而被动等待连接建立的应用进程叫服务器
「TCP连接管理」连接的建立
- 客户端发送连接请求报文段,无应用层数据
- SYN=1
- seq=x(随机产生)
- 服务器端为该TCP连接分配缓存和变量,并向客户端返回确认报文段,允许连接,无应用层数据
- SYN=1
- seq=y(随机)
- ACK=1
- ack=x+1
- 客户端为该TCP连接分配缓存和变量,并向服务器端返回确认的确认,可以携带数据
- SYN=0
- seq=x+1
- ACK=1
- ack=y+1
SYN洪泛攻击
- 一直发送第一次握手的SYN数据包,并不进行确认,导致服务器有大量挂起等待确认的TCP连接,消耗CPU和内存,进而导致死机
- 解决方法:SYN cookie
「TCP连接管理」TCP连接释放
TIP
- 参与一条TCP连接的两个进程中的任何一个都能终止该连接
TCP连接释放的过程(四次握手)
- 客户端发送连接释放报文段,停止发送数据,主动关闭TCP连接,转为FIN-WAIT-1状态
- FIN=1
- seq=u
- 服务器端回送一个确认报文段,并转为CLOSE-WAIT状态;客户到服务器这个方向的连接就释放了(半关闭状态),客户端收到这个确认段后转为FIN-WAIT-2状态
- ACK=1
- seq=v
- ack=u+1
- 服务器端发完数据,就发出连接释放报文段,主动关闭TCP连接,转为LAST-ACK状态
- FIN=1
- seq=w
- ACK=1
- ack=u+1
- 客户端回送一个确认报文段,转为TIME-WAIT状态,再等到时间等待计时器设置的2MSL(最长报文段寿命)后,连接彻底关闭
- seq=u+1
- ACK=1
- ack=w+1
2MSL的意义
防止服务器端因为未收到客户端的确认报文段导致无法关闭
防止丢失的报文段:在发送最后一个 ACK 报文段后,主动关闭方进入 2MSL 等待时间。这确保了如果最后一个 ACK 报文段丢失了,被动关闭方会重新发送 FIN 报文段,主动关闭方可以再次发送 ACK 报文段进行确认。这样可以确保被动关闭方最终能接收到 ACK 并顺利关闭连接。
- 防止旧连接的数据干扰新连接:2MSL 等待时间还可以确保旧连接的所有报文段都已经从网络中消失。当等待时间结束时,任何旧的报文段都已经过期,不会与新建立的连接混淆。这是因为网络中的任何旧报文段在 2MSL 时间内都会失效,这样就避免了在相同 IP 地址和端口号的情况下,新旧连接报文段的混淆。
「TCP」可靠传输
TIP
- 可靠:保证接收方进程从缓存区读出的字节流与发送方发出的字节流是完全一样的
校验
- 与UDP类似,通过伪首部进行检验和校验。
序号
- 为传输流中的每一个字节进行编号,将缓冲区中的字节组成若干个TCP段(数据报),通过确认号和序号的机制进行发送
确认
- 接收方收到报文段后,返回确认字段,确认字段中的确认号为下一个期望收到的起始字节编号。
- 捎带确认:接收方将确认字段捎带在自己要发送的数据中(ACK=1,使用相应的确认号即可)
- 累计确认:只确认到第一个丢失为止的字节
- 此时接收方返回的确认号为4
- 7、8仍然正常接收
- 发送方重新发送4、5、6
- 接收方收到后返回的确认号为9
重传
超时重传:TCP的发送方在规定的时间(重传时间RTTs)内没有收到确认就要重传已发送的报文段,RTTs本质是加权平均往返时间
- 重传时间过短:太长的数据报来不及发送完毕
- 重传时间过长:增加网络空闲时间,降低传输效率
TCP采用自适应算法,动态改变重传时间RTTs
冗余ACK(冗余确认)
- 每当比期望序号大的失序报文段到达时,发送一个冗余ACK,指明下一个期待字节的序号
例:发送方已发送1,2,3,4,5报文段
- 接收方收到1,返回给1的确认(ACK=2)
- 接收方收到3,返回给1的确认(ACK=2,冗余ACK)
- 接收方收到4,返回给1的确认(ACK=2,冗余ACK)
- 接收方收到5,返回给1的确认(ACK=2,冗余ACK)
- 发送方收到3个对于报文段1的冗余ACK
- 发送方认定2丢失,重传2
「TCP」流量控制
- TCP利用滑动窗口机制实现流量控制。
- 接收方根据自己的缓冲区大小,动态的通过窗口字段调整发送方发送窗口的大小。
- 发送方窗口大小取接收窗口rwnd和拥塞窗口cwnd的最小值。
- 拥塞窗口:发送方根据自己估算的网络拥塞程度而设置的窗口值,反映网络当前容量。
- 当接收方通过确认重传机制进行字节编号确认时,会连带着修改发送方的允许发送窗口大小。
例:A向B发送数据,连接建立时,B的初始rwnd=400(B),设每一个报文段100B,报文段序号初始值为1
- ”死锁“情况:
- 若接收方发送的允许发送的确认信息丢包,则此时会出现“死锁”情况。
- 即发送方窗口大小仍然为0,无法发送数据;
- 接收方一直等待发送方发送新数据,没有新的确认信息。
- 解决方法:
- TCP为每一个连接设有一个持续计时器,只要TCP连接的一方收到对方的零窗口通知,就启动持续计时器。
- 到时间则发送一个零窗口的探测报文段,并重置计时器时间。
滑动窗口的大小
- 滑动窗口过小:产生太多ACK
- 滑动窗口过大:路由器发生拥挤,主机可能丢失分组
「TCP」拥塞控制
- 拥塞控制:全局性的控制
- 流量控制:端到端的控制
- 拥塞控制的意义:防止过多的数据注入到网络中
拥塞控制的前提
- 数据单方向传送,而另一个方向只传送确认
- 接收方总是有足够大的缓存空间(rwnd→∞rwnd→∞),因而发送窗口大小取决于拥塞程度
「TCP拥塞控制」慢开始和拥塞避免
- cwnd(Congestion Window) 的单位是报文段
- 默认的初始值为1(或MSS长度)
- 传输轮次:从发送一批报文段到收到它们的确认所用的时间,单位为往返时延RTT
- 慢开始:cwnd的增加速度为指数型增长,起始为 1,增长为2,4,8,16 ......
- 拥塞避免:当cwnd的值达到**慢开始门限ssthresh(Slow Start Threshold,慢启动阈值)**时,增长模式变为每次 +1
- 网络发生拥塞
- 将cwnd置为 1,重新进入慢开始算法
- 将ssthresh置为当前cwnd的一半,提前进入拥塞避免算法
「TCP拥塞控制」快重传和快恢复
- 慢开始&拥塞恢复:初始阶段与慢开始和拥塞避免类似
- 快重传:采用冗余ACK机制,当收到3次连续的冗余ACK时执行快重传,重新发送丢失帧
- 快恢复:当发送拥塞时,只需要将窗口降低到新的慢开始门限ssthresh,再次进入拥塞避免算法即可
- 新的ssthresh为发生拥塞时cwnd的一半
- 快恢复算法不用将cwnd降低到 1