TCP协议概述
简述
面向连接(虚连接)的传输控制协议TCP
传送数据之前必须建立连接,数据传送结束之后要释放连接
不提供广播或多播服务
由于TCP要提供可靠的面向连接的传输服务,因此不可避免的增加了许多开销,确认、流量控制、计时器及连接管理等
可靠,面向连接,时延大,适用于大文件
特点
(1)TCP是面向连接(虚连接)的传输层协议
需要在端系统中维护连接状态:接收和发送缓存、拥塞控制参数和序号与确认号参数
(2)每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的:不提供广播或多播服务
(3)TCP提供可靠交付的服务,无差错、不丢失、不重复、按序到达。可靠有序,不丢不重
(4)TCP提供全双工通信:TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据
- 发送缓存
- 准备发送的数据
- 已经发送但尚未收到确认的数据
- 接收缓存
- 按序到达但尚未被接收应用程序读取的数据
- 不按序到达的数据
(5)TCP面向字节流
字节流:流入到进程或从进程流出的字节序列
TCP和应用程序的交互是一次一个数据块(大小不等),但TCP把应用程序传递下来的数据看成仅仅是一连串的无结构的字节流
TCP传送时是按照一个一个字节来传送的(但并不是每个报文只传送一个字节)
TCP报文段首部格式
- 源端口和目的端口字段,各占2个字节
- 端口是运输层与应用层的服务接口
- 序号字段(seq),占4个字节
- 在一个TCP连接中传送的字节流中的每一个字节都按顺序编号
- 本字段表示本报文所发送数据的第一个字节的序号
- 确认号字段(ack),占4个字节
- 期望收到对方下一个报文段的第一个数据字节的序号
- 若确认号为N,则证明序号N-1为止的所有数据都已正确收到
- 数据偏移(首部长度)字段,占4位
- 表示TCP报文段的数据起始距离TCP报文段的起始处有多远
- 以4B(32位)为单位,即1个数值是4B
- 此数值最大是15,因此TCP首部最长是60B
- 保留字段,占6位
- 保留为以后使用,目前应置0,该字段可忽略不计
- 控制位字段
- 紧急位URG(Urgent)
- URG=1时,表明此报文段中有紧急数据,是高优先级的数据,应尽快传送,不用在缓存里排队,配合紧急指针字段使用
- 确认位ACK (Acknowledgement)
- ACK=1时确认号字段有效
- 在TCP连接建立后所有传送的报文段都必须把ACK置为1
- 推送位PSH(Push)
- PSH=1时,接收方尽快交付应用程序进程,不再等到缓存填满再向上交付
- 复位位RST(Reset)
- RST=1时,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立传输连接
- 同步位SYN
- SYN=1时,表明是一个连接请求/连接接收报文
- 终止位FIN(Finish)
- FIN=1时,表明此报文段发送方数据已发完,要求释放连接
- 紧急位URG(Urgent)
- 窗口字段,占2字节
- 指的是发送本报文段的一方的接收窗口,即现在允许对方发送的数据量
- 窗口值的单位是字节
- 校验和字段,占2字节
- 检验首部+数据
- 检验时要加上12B伪首部,
- 第四个字段(协议字段)为6
- 紧急指针字段,占16位
- URG=1时才有意义,指出本报文段中紧急数据的字节数
- 数据从第一个字节到紧急指针所指字节就是紧急数据
- 选项字段,长度可变
- 最大报文长度MSS(Maximum Segment Size):TCP报文中数据字段的最大长度
- 窗口扩大
- 时间戳
- 选择确认
- …
- 填充字段
- 为了使整个首部的长度是4字节的整数倍
TCP连接管理
三个阶段:连接建立、数据传送、连接释放
TCP连接的建立采用客户服务器方式C/S
- 客户机:主动发起连接建立的应用进程
- 服务器:被动等待连接建立的应用进程
需要解决以下问题
- 要使每一方都能确知对方的存在
- 要允许双方协商一些参数
- 能够对运输实体资源进行分配
连接建立
三次握手
(1)客户端发送连接请求报文段
无应用层数据
连接请求报文不携带数据,但要消耗一个序号
- SYN=1
- seq(序号)=x(随机)
(2)服务器为该TCP连接分配缓存和变量,并向客户端返回确认报文段,允许连接
无应用层数据
确认请求报文不携带数据,但要消耗一个序号
- SYN=1
- ACK=1
- seq=y(随机)
- ack(确认号)=x+1
(3)客户端为该TCP连接分配缓存和变量,并向服务器端返回确认的确认,可以携带数据
- SYN=0
- ACK=1
- seq=x+1
- ack=y+1
SYN洪泛攻击
发生在OSI第四层,利用TCP协议的三次握手
攻击者发送TCP SYN,当服务器返回ACK后,该攻击者不对其进行确认,那么这个TCP连接就处于挂起状态(半连接状态)。攻击者发送非常大量的这种TCP连接,在服务器上,这些TCP连接会因为挂起状态而消耗CPU和内存
解决方法:设置SYN Cookie
数据传送
连接释放
四次挥手
(1)客户端发送连接释放报文段,停止发送数据,主动关闭TCP连接
- FIN=1
- seq=u
(2)服务器端会回送一个确认报文段,客户到服务器这个方向的连接就释放了(半关闭状态)
- ACK=1
- seq=v
- ack=u+1
(3)服务端发完数据,就发出连接释放报文段,主动关闭TCP连接
- FIN=1
- ACK=1
- seq=w:取决于第三个阶段,服务器端发送的数据量的多少
- ack=u+1
(4)客户端回复一个确认报文段,再等到时间等待计时器设置的2MSL(最长报文段寿命)后,连接彻底关闭
- ACK=1
- seq=u+1
- ack=w+1
全过程11种状态
状态 | 说明 |
---|---|
LISTEN | 正在等待一个来自任何远程TCP和端口的连接请求 |
SYN-SENT | 在已经发出一个连接请求后正在等待一个匹配的确认连接请求 |
SYN-RECEIVE | 在已经收到并发出了一个连接请求后等待一个证实连接请求的确认 |
ESTABLISHED | 一个打开的连接。通过此连接接收到的数据能够被传递到用户。 该状态是此连接的数据传输阶段的正常状态 |
FIN-WAIT1 | 正在等待一个针对先前发送的连接终止请求的确 |
FIN-WAIT2 | 正在等待一个来自远程TCP的连接终止请求 |
CLOSE-WAIT | 正在等待一个来自本地用户的连接终止请求 |
CLOSING | 正在等待一个来自远程TCP的连接终止请求的确认 |
LAST-ACK | 正在等待一个先前发往远程TCP的连接终止请求的确认(包括对其连接终止请求的确认) |
TIME-WAIT | 等足够的时间以确保远程TCP接收到了其连接终止请求的确认 |
CLOSED | 根本不存在连接的状态 |
TCP可靠传输
- 可靠
- 保证接收方进程从缓存区读出的字节流与发送方发出的字节流是完全一样的
- 机制:
- 校验、序号、确认、重传
校验
与UDP校验一样,增加伪IP报文首部
序号
一个字节占一个序号
序号字段:一个报文段的第一个字节的序号
序号字段能保证数据有序提交给应用层
确认
确认号字段是期望收到对方的下一个报文段的数据的第一个字节的序号
TCP默认使用累计确认:只确认数据流中至第一个丢失字节为止的字节
捎带确认:在传送的数据中捎带确认信息
重传
超时重传
只要计时器设置的重传时间到期还没有收到确认,就要重传这一报文段
动态改变重传时间
RTT
往返时间(Round-Trip Time,RTT):一个报文发出的时间和收到相应确认的时间之差
RTTs
当第一次测量RTT样本时,RTTs的值为所测量到的RTT样本的值,以后的每一次采用以下公式:
新的RTTs=(1 - α)*(旧的RTTs) + α *(新的RTT样本),其中0≤α<1
若α很接近0,表示新的RTTs的值和旧的RTTs的值相比变化不大,即受新的RTT样本影响不大(RTT值更新较慢)
若α很接近1,表示新的RTTs的值受新的RTT样本影响较大(RTT值更新较快)
[RFC 2988]推荐的α值为0.125
RTTD
RTTD是RTT的偏差的加权平均值,它与RTTs和新的RTT样本之差有关
当第一次测量时,RTTD取RTT样本值的一半,以后的每一次采用以下公式:
新的RTTD=(1 - β)*(旧的RTTD)+ β * | RTTs - 新的RTT样本 |
β是个小于1的系数,推荐值是0.25
RTO
超时计时器设置的超时重传时间RTO(Retransmission Time-Out),使用以下公式计算
RTO = RTTs + 4 * RTTD
冗余ACK(冗余确认)
每当比期望序号大的失序报文段到达时,发送一个冗余ACK,指明下一个期待到达的序号
当发送方接收到对同一个报文段的3个冗余ACK时,就可以认为跟在这个被确认报文段之后的报文段已经丢失
快速重传
发送方已发送1,2,3,4,5报文段
接收方接收到1,返回给1的确认(确认号为报文段2的第一个字节)
接收方接收到3,仍返回给1的确认(确认号为报文段2的第一个字节)
接收方接收到4,仍返回给1的确认(确认号为报文段2的第一个字节)
接收方接收到5,仍返回给1的确认(确认号为报文段2的第一个字节)
发送方收到3个对于报文段1 的冗余ACK -> 认为2报文段丢失,重传2号报文段(快速重传)
TCP流量控制
流量控制:让发送方慢点,要让接收方来得及接收
流量控制是一种速度匹配服务(匹配发送方的发送速率和接收方的接收速率)
防止丢包严重
滑动窗口机制
TCP使用滑动窗口机制实现流量控制
- 在通信过程中,接收方根据自己接收缓存的大小,动态地调整发送方的发送窗口大小,即接收窗口rwnd
- 接收方设置确认报文段的窗口字段来将rwnd通知给对方
- 发送方的发送窗口 = Min{接收窗口rwnd,拥塞窗口cwnd}
- 接收窗口
- 接收方根据接收缓存设置的值,并告知给发送方,反映接收方容量
- 由接收方根据其放在TCP报文的首部的窗口字段通知发送方
- 拥塞窗口
- 发送方根据自己估算的网络拥塞程度而设置的窗口值,反映网络当前容量
- 只要网络没有出现拥塞,拥塞窗口就增大一些,以便发送更多分组出去;但只要网络出现拥塞,拥塞窗口就减小一些,以减少注入网络中的分组数
- 接收窗口
- 发送窗口大小可以动态变化
A向B发送数据,连接建立时,B告诉A:“我的rwnd=400(字节)”,设每一个报文段100B,报文段序号初始值为1
- 避免死锁
- TCP为每一个连接设有一个持续计时器,只要TCP连接的一方收到对方的零窗口通知,就启动持续计时器
- 若持续计时器设置的时间到期,就发送一个零窗口探测报文段。接收方收到探测报文段时给出现在的窗口值
- 若窗口仍然是0,那么发送方就重新设置持续计时器
TCP拥塞控制
出现拥塞的条件
- 对资源需求的总和 > 可用资源
- 网络中有许多资源同时呈现供应不足 -> 网络性能变坏 -> 网络吞吐量将随输入负荷增大而下降
- 拥塞控制
- 防止过多的数据注入到网络中。(全局性)
- 四种算法:慢开始、拥塞避免、快重传、快恢复
慢开始和拥塞避免
假定:
-
数据单方向传输,而另一个方向只传送确认
-
接收方总是有足够大的缓存空间,因而发送窗口大小取决于拥塞控制
发送窗口 = Min{接收窗口rwnd,拥塞窗口cwnd}
- 传输轮次
- 发送一批报文段并收到它们确认的时间
- 即一个往返时延RTT
- 开始发送一批拥塞窗口内的报文段到开始发送下一批拥塞窗口内的报文段的时间
快重传和快恢复
其他
(1)传输层和数据链路层的流量控制的区别
传输层定义了端到端用户之间的流量控制,数据链路层定义了两个中间的相邻结点的流量控制。另外,数据链路层的滑动窗口协议大小不能动态变化,传输层则可以动态变化
(2)拥塞控制和流量控制的区别
拥塞控制是为了让网络能够承受现有的网络负荷,它是一个全局性的过程,涉及所有的主机、所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是指点对点的通信量的控制,即接收端控制发送端,它所要做的就是抑制发送端发送数据的速率,以便使接收端来得及接收