计算机网络-传输层
计算机网络理论,传输层。
概述
由传输层实现可靠传输:差错控制、顺序控制、拥塞控制等。
传输层和网络层的区别:
- 网络层实现主机之间的逻辑通信
- 传输层实现应用进程之间的逻辑通信
- 真正的端到端通信
主要协议:
- 传输控制协议TCP:可靠传输协议
- 用户数据报协议UDP:不可靠传输协议
传输层区分上层应用进程的手段:端口(port):
- TCP/IP使用16位整数作为端口号
- 知名端口(well-known):0~1023,如HTTP(80)、FTP(21)、Telnet(23)
- 登记端口:1024~49151
- 客户端口或短暂端口:49152~65535
用户数据报协议UDP
UDP只在IP数据包的服务上增加了端口和差错检测功能。
UDP协议的特点:
- 无连接,即发送数据之前不需要建立连接
- 使用尽最大努力交付,即不保证可靠交付,同时也不使用拥塞控制
- 是面向报文的。没有拥塞控制,很适合多媒体通信的要求
- 支持一对一、一对多、多对一和多对多的交互通信
- 首部开销小,只有8个字节
UDP首部格式
UDP数据报包括2个字段:首部和数据字段。
首部共4个字段,8字节:
- 源端口号(2字节)
- 目的端口号(2字节)
- 数据报长度(2字节)
- 校验和(2字节)
伪首部(pseudo header):用于计算校验和,包括源IP地址、目的IP地址、协议号、UDP长度,不实际传输。
校验和的计算与IP包头校验和计算类似:
- IP只计算包头校验和,UDP计算整个数据报的校验和
- 计算校验和时要添加伪头部
- 数据部分的奇数字节需填充全0字节
在接收方,如果在目的端口号上没有应用进程接收数据,则向源主机返回ICMP的“目的不可达”报文。
传输控制协议TCP
TCP的主要特点:
- TCP 是面向连接的传输层协议
- 传输数据前必须先建立连接,数据传输完毕后要释放连接
- 每一条TCP 连接只能有两个端点(endpoint),每一条TCP 连接只能是 点对点的(一对一)
- TCP 提供可靠交付的服务
- 无差错、不丢失、不重复、按序到达
- TCP 提供全双工通信
- 在一个连接上,通信双方可同时向对方传输数据
- 面向字节流
- 认为在TCP连接上传输的是字节流
- 应用程序以数据块为单位与TCP交互,但TCP将其视为无结构的字节流
- 发送方应用进程发出的数据块与接收方应用进程收到的数据块可能没有一一对应关系,但数据保证一致
TCP连接
TCP把连接作为最基本的抽象,每一条TCP连接有两个端点。
TCP连接的端点不是主机,不是主机的IP地址,不是应用进程,也不是传输层的协议端口,TCP 连接的端点叫做套接字(socket)或插口。端口号拼接到IP地址后即构成了套接字。
\[socket = (<IP addr>:<port>)\]每一条TCP链接唯一地被通信两端的两个套接字确定。
TCP报文段
- 源端口和目的端口字段:各2字节
- 序号字段:4字节
- 在TCP连接中传送的数据流中的每一个字节都有序号
- 序号字段指本报文段所发送的数据的第一个字节的序号,以字节为单位
- 确认号字段:4字节,期望收到对方的下一个报文段的数据的第一个字节的序号
- 例:收到对方的报文段中序号为501,数据长度200字节,则返回报文段确认号=701
- TCP连接是全双工,通信双方可互相发送数据,因此应答与数据一同发送给对方
- 数据偏移(首部长度):4bit,TCP报文段的数据起始位置的偏移,也就是首部的长度,单位是32位字(4字节)
- 保留字段:6bit,保留
- 紧急URG:1bit,为1时,紧急指针字段有效,表明有紧急数据,应尽快传送
- 确认ACK:1bit,为1时,确认号字段有效;为0时,确认号无效
- 推送PSH:1bit,为1时,接收方将尽快向应用进程交付此报文段,而不是等到整个缓存填满
- 复位RST:1bit,为1时,表明TCP连接出现严重差错(如由于主机崩溃),须 释放连接后重新建立连接
- 同步SYN:1bit,为1时,表示这是一个连接请求或连接接受报文
- 终止FIN:1bit,为1时,表示要求释放TCP连接
- 窗口大小:2字节,用来让对方设置发送窗口的依据,单位为字节
- 检验和:2字节,伪首部+首部+数据的校验和
- 伪首部:与UDP相同,协议号为6 紧急指针:2字节,指出本报文段中紧急数据共有多少个字节(紧急数据放在数据的最前面)
- 选项:长度可变,最长40字节
- 最早定义的一种选项:最大报文段长度MSS(Maximum Segment Size),告知对方报文段中数据最大长度,双方可使用不同的MSS,缺省MSS=536字节
- 后续增加的选项:窗口扩大选项、时间戳选项、选择确认选项
- 填充字段:为了使整个首部长度是4字节的整数倍
TCP可靠传输的实现
滑动窗口
TCP基于滑动窗口协议实现可靠传输和流量控制,滑动窗口以字节为单位。
窗口大小:
- 对方发送的报文告知
- 拥塞控制
根据收到对方的TCP报文段头部中“acknowledge number”字段,窗口向前滑动,“acknowledge number”字段表示在此序号之前的数据已被正确接收。
发送缓存用来暂时存放:
- 发送应用进程传送给TCP,但尚未发出的数据
- 已发送,但尚未收到确认的数据
接收缓存用来暂时存放:
- 按序到达的、但尚未被接收应用进程读取的数据
- 未按序到达的数据
超时重传
TCP使用超时重传机制来保证可靠传输:
- 发送方发送数据后启动计时器
- 如果计时器超时,发送方重传数据
TCP采用一种自适应算法计算超时重传时间。
TCP保留了\(RTT\)的一个加权平均往返时间\(RTT_S\)(又称为平滑的往返时间),每次收到一个新的\(RTT\),更新\(RTT_S\):
\[RTT_S = (1-\alpha) \times RTT_S + \alpha \times RTT\]其中 \(\alpha\)是一个常数,取值范围为0~1,通常取值0.125。
超时重传时间\(RTO\)应略大于\(RTT_S\),使用如下公式计算:
\[RTO = RTT_S + 4 \times RTT_{D}\]其中\(RTT_{D}\)是\(RTT\)的偏差加权平均值,表示\(RTT\)的变化情况。计算公式如下:
\[RTT_{D} = (1-\beta) \times RTT_{D} + \beta \times |RTT - RTT_S|\]其中\(\beta\)是一个常数,取值范围为0~1,通常取值0.25。第一次计算时,\(RTT_{D} = RTT/2\)。
TCP流量控制
TCP连接建立过程中,将自己的接收窗口大小告知对方。TCP报头中都携带有窗口大小字段,告知对方自己接收窗口的剩余大小(即可接收的字节数)。发送方的发送窗口应不大于对方的接收窗口。
若接收方的接收窗口为0,发送方应停止发送数据,等待接收方通知窗口大小。如果这个报文丢失,会造成死锁,需要通过持续计时器来解决。
持续计时器(persistence timer):
- TCP为每一个连接设有一个持续计时器
- 只要一方收到对方的零窗口通知,就启动持续计时器
- 若持续计时器设置的时间到,就发送一个零窗口探测报文段(仅携带1字节的数据),而对方在确认这个探测报文段时给出当前窗口值
- 若窗口仍然是零,则收到这个报文段的一方就重新设置持续计时器
- 若窗口不是零,则死锁的僵局就可以打破了
可以用不同的机制来控制TCP报文段的发送时机:
- 缓存数据达到一定量就发送– TCP维持一个变量,它等于最大报文段长度MSS
- 只要缓存中存放的数据达到MSS字节时,就组装成一个TCP报文段发送出去
- 应用进程控制
- 由发送方的应用进程指明要求发送报文段,即推送(push)操作
- 定时发送
- 发送方的一个计时器期限到了,这时就把当前已有的缓存数据装入报文段(但长度不能超过MSS)发送出去
TCP拥塞控制
四种拥塞控制算法:
- 慢启动(slow start)
- 拥塞避免(congestion avoidance)
- 快重传(fast retransmit)
- 快恢复(fast recovery)
慢启动和拥塞避免
试探性地从小到大逐渐增大发送窗口。
拥塞窗口cwnd (congestion window):
- 发送方维持拥塞窗口,它是一个状态变量
- 拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化
- 发送方让自己的发送窗口等于拥塞窗口,如再考虑到接收方的接收能力,则发送窗口还可能小于拥塞窗口
使用慢启动时,每经过一个传输轮次,拥塞窗口cwnd就加倍。
拥塞避免算法的思路:让拥塞窗口cwnd缓慢地增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍,使拥塞窗口cwnd按线性规律缓慢增长。
为防止拥塞窗口cwnd增长过大导致拥塞,设置一个慢启动门限 (ssthresh):
- cwnd < ssthresh时,使用慢启动算法
- cwnd > ssthresh时,停止使用慢启动算法而改用拥塞避免算法
- cwnd = ssthresh时,可使用慢启动算法或拥塞避免算法
拥塞发生时的处理:
- 无论在慢启动阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(没有按时收到确认),就要把慢启动门限ssthresh改为出现拥塞时的发送方窗口值的一半(但不能小于2)
- 然后把拥塞窗口cwnd重新设置为1,执行慢启动算法
- 这样做的目的:迅速减少注入到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕
上面两个过程有对应的名字:乘法减小和加法增大。
乘法减小(multiplicative decrease):
- 不论在慢启动阶段还是拥塞避免阶段,只要出现一次超时(即网络拥塞),就把慢启动门限ssthresh减小到拥塞窗口的一半
- 当网络频繁出现拥塞时,ssthresh值下降得很快,以大大减少注入到网络中的分组数
加法增大(additive increase):
- 在拥塞避免阶段,每经过一个往返时间RTT,就把发送方的拥塞窗口cwnd加1
快重传和快恢复
快重传算法:
- 如果发送方在超时时间内未收到确认报文,说明网络中发生了拥塞,此时发送方应尽早地减小窗口宽度
- 每当接收方收到一个失序的报文段,就发出重复确认,以便使发送方及早知道有报文段没有到达接收方
- 发送方只要接连收到三个重复确认就应当立即重传对方尚未收到的报文段
快恢复算法:
- 当发送端收到连续三个重复的确认时,就进行“乘法减小”,把慢启动门限ssthresh减为当前拥塞窗口宽度的一半
- 接下来不执行慢启动算法,而是设置为慢启动门限ssthresh减半后的数值,然后开始执行拥塞避免算法(“加法增大”),使拥塞窗口缓慢地线性增大
- 发送方认为现在网络很可能没有发生拥塞(仅有拥塞征兆),因为拥塞时不会有连续多个报文段到达接收
综上,发送窗口的上限为接收方窗口和拥塞窗口的最小值:
\[swnd = \min(cwnd, rwnd)\]TCP连接管理
TCP连接的建立都是采用客户/服务器方式
- 客户(client):主动发起连接建立的应用进程
- 服务器(server):被动等待连接建立的应用
TCP连接的建立
TCP连接的建立采用三次握手(three-way handshake):
- A向B发出连接请求报文段,其首部中的SYN=1,并选择序号seq=x,表明传送数据时的第一个数据字节的序号是x
- B收到连接请求后,如同意,则发回确认,其中SYN=1,ACK=1,确认号ack=x+1,自己选择的序号seq=y
- A收到后向B给出确认,其ACK=1,确认号ack=y+1,B收到后连接建立
3次握手的目的:防止已失效的连接请求在服务器端占用资源。
3次握手的安全问题:TCP SYN Flooding攻击
- 攻击者向服务器发送大量的SYN包,服务器回复ACK包,但攻击者不回复ACK包,导致服务器资源耗尽
- 防范:SYN Cookies
TCP连接的释放
连接的释放可由任一方发起:
- A发送报文段,其首部的FIN=1,序号seq=u
- B发出确认,ACK=1,确认号ack=u+1,序号seq=v
- A->B方向的连接被释放,此时连接处于半关闭状态,B若发送数据,A仍要接收
- B发送报文段,FIN=1,ACK=1,确认号ack=u+1,序号seq=w
- A发出确认,ACK=1,确认号ack=w+1,连接释放
TCP连接必须经过时间2MSL后才真正释放掉。MSL是报文段最长生存时间,通常取值小于2分钟。
- 2MSL是为了保证A发送的最后一个ACK报文段能够到达B,B收到后再发送一个ACK报文段给A,这样A和B都能释放连接
- 2MSL是为了防止“已失效的连接请求报文段”出现在本连接中