- 点对点 一个发送方,一个接收方
- 可靠的、按序的字节流
- 流水线机制 TCP拥塞控制和流量控制机制 设置窗口尺寸
- 发送方/接收方缓存
- 全双工(full-duplex) 同一连接中能够传输双向数据流
- 面向连接 1. 通信双方在发送数据之前必须建 立连接。 2. 连接状态只在连接的两端中维护 ,在沿途节点中并不维护状态。3. TCP连接包括:两台主机上的缓 存、连接状态变量、socket等
-
TCP报文段格式

固定的首部不算紧急指针和保留 源端口和目的端口字段——各占 2 字节。端口是运输层与应用层的服务接口。运输层的复用和分用功能都要通过端口才能实现
- 序号字段——占 4 字节。TCP 连接中传送的数据流中的每一个字节都编上一个序号。序号字段的值则指的是本报文段所发送的数据的第一个字节的序号。seq
- 确认号字段——占 4 字节,是期望收到对方的下一个报文段的数据的第一个字节的序号。
- 数据偏移(即首部长度)——占 4 位,它指出 TCP 报文段的数据起始处距离 TCP 报文段的起始处有多远。“数据偏移”的单位是 32 位字(以 4 字节为计算单位)。
- 保留字段——占 6 位,保留为今后使用,但目前应置为 0。
- 紧急 URG —— 当 URG 1 时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据)。
- 确认 ACK —— 只有当 ACK 1 时确认号字段才有效。当 ACK 0 时,确认号无效。
- 推送 PSH (PuSH) —— 接收 TCP 收到 PSH = 1 的报文段,就尽快地交付接收应用进程,而不再等到整个缓存都填满了后再向上交付
- 复位 RST (ReSeT) —— 当 RST 1 时,表明 TCP 连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。
- 同步 SYN —— 同步 SYN = 1 表示这是一个连接请求或连接接受报文。
- 终止 FIN (FINish) —— 用来释放一个连接。FIN 1 表明此报文段的发送端的数据已发送完毕,并要求释放运输连接。
- 窗口字段 —— 占 2 **字节**,用来让对方设置发送窗口的依据,单位为字节。
- 检验和 —— 占 2 字节。检验和字段检验的范围包括首部和数据这两部分。在计算检验和时,要在 TCP 报文段的前面加上 12 字节的伪首部。
- 紧急指针字段 —— 占 16 位,指出在本报文段中紧急数据共有多少个字节(紧急数据放在本报文段数据的最前面)。URG= 1 才有用
- 选项字段 —— 长度可变。TCP 最初只规定了一种选项,即最大报文段长度 MSS。MSS 告诉对方 TCP:“我的缓存所能接收的报文段的数据字段的最大长度是 MSS 个字节。”
MSS (Maximum Segment Size) 是 TCP 报文段中的数据字段的最大长度。 数据字段加上 TCP 首部才等于整个的 TCP 报文段。 所以,MSS是“TCP 报文段长度减去 TCP 首部长度”
- 填充字段 —— 这是为了使整个首部长度是 4 字节的整数倍。
TCP可靠传输原理
https://www.cnblogs.com/williamjie/p/9390183.html
TCP在IP层提供的不可靠服 务基础上实现可靠数据传输 服务
触发重传的事件
- 超时
- 收到重复ACK
流水线机制
GBN/SR累积确认
IP提供的服务是尽力交付的服务,也是不可靠的服务。但是TCP在IP之上提供了可靠度传输服务。TCP采用了流水线下的可靠数据传输协议,但是在差错恢复时,并没有简单的采取GBN协议或者选择重传协议,而是将二者结合了起来。<br /> TCP采用了累积确认的方式,这类似于GBN,即如果TCP发送了对某个序号N的确认,则表明**在N之前的所有字节流都已经被正确接收**。但是另一方面,TCP又不会像GBN协议那样简单丢弃失序到达的报文段,而是会将它们**缓存起来**,但是这些被缓存的报文段不会**逐个被确认**。当发生超时时,TCP只会重传发生超时的那一个报文段。<br /> TCP还允许接收方选择性的确认失序到达的分组,而不是累积的对最后一个确认最后一个正确到达的分组,将它与TCP所采取的选择重传结合起来看就很想选择重传协议的工作机制。因此说TCP的差错恢复结合了GBN和选择重传。
TCP使用单一重传定时器
选择重传中每个报文段都有自己的超时值,TCP采用了RFC2988建议的机制用一个单一定时器来完成该功能。RFC2988定义的原则:
- 发送TCP分段时,如果还没有重传定时器开启,那么开启它。
- 发送TCP分段时,如果已经有重传定时器开启,不再开启它。
- 收到一个非冗余ACK时,如果有数据在传输中,重新开启重传定时器。
- 收到一个非冗余ACK时,如果没有数据在传输中,则关闭重传定时器。
过程如下
- 发送分组
TCP会为发送的每一个分组分配一个唯一的序号,该序号和ISN以及该报文段在字节流中的位置有关(第一个字节的编号)。序号被填入TCP头部的序号字段。如果重传定时器还没有运行,则会启动重传定时器。设置超时时间
- 接收到ACK
由于是累积确认的,因此如果收到的ACK是合法的,即是对已发送但未被确认的报文段的确认,则更新send_base,并且如果还有未被确认的已发送的报文段,则重启重传定时器。
- 超时
重传引起超时的报文段,并重启定时器。TCP的重传不一定是重传引起超时的报文段本身,TCP可能重新进行分组然后重传,唯一被保证的是所有数据都会被传输。
- ACK
每个TCP报文段的TCP头部都固定包含了ACK域,如果在传输中,为了确认一个报文段而单独发送一个ACK,则该ACK就是一个数据部分长度为0的特殊TCP报文段,如果这样的分段太多,网络的利用率就会下降。为此,TCP采取了延迟确认的机制。其工作过程:
如果收到的报文段的序号等于rcv_base,并且所有在rvc_base之前的报文段的确认都已经被发送,则只更新rcv_base,但是延迟该报文段的ACK的发送,最多延迟500ms。延迟的ACK可能会在接收端有数据要发送给发送端时被发送或者在接收端有多个ACK需要被发送给发送端时被发送。
如果收到的报文段的序号等于rcv_base,并且有延迟的ACK待发送,则更新rcv_base,并发送累积的ACK以确认这两个按序报文段
如果收到的报文段的序号大于rcv_base,则发送冗余的ACK,即重传对已经确认过的最后一个按序到达的报文段的ACK
快速重传
快速重传:在定时器超时之前即进行重传
倍数增加的重传间隔
在发生超时重传时,TCP不是以固定的时间间隔来重传的,而是会再每次重传时都将下一次重传的间隔设置为上次重传间隔的2倍,因此重传间隔是倍数增加的。直到收到确认或者彻底失败。由于正常发送报文段时,重传定时器的超时值为EstimateRTT + 4 * DevRTT,因此第一重传时会将下一次的超时时间设置为**2倍**的该值,依次类推。
快速重传
倍数增加的重传间隔会增大端到端的时延,使得发送端可能不得不等待很长时间才能重传报文段。冗余ACK使得TCP可以得到分组丢失的线索。TCP基于冗余ACK提供了一种快速重传机制。其原理是:如果收到了对相同数据的三个冗余的ACK,发送端就认为跟在这个被确认了**三次**的报文段之后的报文段丢失了,因此重传它,而不是等待它的超时定时器到期。这就是快速重传。<br />
发送缓存用来暂时存放: 发送应用程序传送给发送方 TCP 准备发送的数据; TCP 已发送出但尚未收到确认的数据。
接收缓存用来暂时存放: 按序到达的、但尚未被接收应用程序读取的数据; 不按序到达的数据
TCP流量控制
利用滑动窗口实现
接收方为TCP连接分配buffer
- 上层应用可能处理 buffer中数据的速度 较慢
- 发送方不会传输的太多 、太快以至于淹没接收方 (buffer溢出)
- 速度匹配机制
TCP建立连接和释放连接
连接建立

- A 的 TCP 向 B 发出连接请求报文段,其首部中的 同步位 SYN = 1,并选择序号 seq = x,表明传送 数据时的第一个数据字节的序号是 x
B 的 TCP 收到连接请求报文段后,如同意,则发回确认。
B 在确认报文段中应使 SYN = 1,使 ACK = 1, 其确认号ack = x + 1,自己选择的序号 seq = y。
A 收到此报文段后向 B 给出确认,其 ACK = 1, 确认号 ack = y + 1。 A 的 TCP 通知上层应用进程,连接已经建立。
B 的 TCP 收到主机 A 的确认后,也通知其上层 应用进程:TCP 连接已经建立。
连接释放

数据传输结束后,通信的双方都可释放连接。 现在 A 的应用进程先向其 TCP 发出连接释放 报文段,并停止再发送数据,主动关闭 TCP 连接。 A 把连接释放报文段首部的 FIN = 1,其序号 seq = u,等待 B 的确认
- B 发出确认,确认号 ack = u +1, 而这个报文段自己的序号 seq = v。 TCP 服务器进程通知高层应用进程。 从 A 到 B 这个方向的连接就释放了,TCP 连接处于半关闭状态。B 若发送数据,A 仍要接收
- 若 B 已经没有要向 A 发送的数据, 其应用进程就通知 TCP 释放连接
- A 收到连接释放报文段后,必须发出确认。在确认报文段中 ACK = 1,确认号 ack = w +1, 自己的序号 seq = u + 1。
TCP的拥塞控制
在某段时间,若对网络中某资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏——产生拥塞(congestion)。 出现资源拥塞的条件: 对资源需求的总和 > 可用资源
- 拥塞控制就是防止过多的数据注入到网络中,使网络中的路由器或链路不致过载。
- 拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。
- 拥塞控制是一个全局性的过程,涉及到所有的主机、所有的路由器,以及与降低网络传输性能有关的所有因素。
流量控制往往指点对点通信量的控制,是个端到端的问题(接收端控制发送端),流量控制所要做的就是抑制发送端发送数据的速率,以便使接收端来得及接收
_
慢开始
发送方维持一个叫做拥塞窗口 cwnd (congestion window)的状态变量。 发送方控制拥塞窗口的原则是:只要网络没有出现拥塞,拥塞窗口就再增大一些,以便把更多的分组发送出去。 但只要网络出现拥塞,拥塞窗口就减小一些,以减少注入到网络中的分组数。
- 在主机刚刚开始发送报文段时可先设置拥塞窗口 cwnd = 1,即设置为一个最大报文段 MSS 的数值。 在每收到一个对新的报文段的确认后,将拥塞窗口加 1(这个1不是指的1个报文段 是指的加倍),即增加一个 MSS 的数值。 用这样的方法逐步增大发送端的拥塞窗口 cwnd,可以使分组注入到网络的速率更加合理。

慢开始门限 ssthresh 的用法如下:
当 cwnd < ssthresh 时,使用慢开始算法。
当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法。
当 cwnd = ssthresh 时,既可使用慢开始算法,也可使用拥塞避免算法。
拥塞避免算法的思路:让拥塞窗口 cwnd 缓慢地增大,即每经过一个往返时间 RTT 就把发送方的拥塞窗口 cwnd 加 1,而不是加倍,使拥塞窗口 cwnd 按线性规律缓慢增长。
当 TCP 连接进行初始化时,将拥塞窗口置为 1。图中的窗口单位不使用字节而使用报文段。 
“乘法减小“
是指不论在慢开始阶段还是拥塞避免阶段,只要出现一次超时(即出现一次网络拥塞),就把慢开始门限值 ssthresh 设置为当前的拥塞窗口值乘以 0.5。 当网络频繁出现拥塞时,ssthresh 值就下降得很快,以大大减少注入到网络中的分组数。
“加法增大”
是指执行拥塞避免算法后,在收到对所有报文段的确认后(即经过一个往返时间),就把拥塞窗口 cwnd增加一个 MSS 大小,使拥塞窗口缓慢增大,以防止网络过早出现拥塞。
加性增—乘性减: AIMD
逐渐增加发送速率,谨慎探测可用带宽,直到发生loss
拥塞避免
让拥塞窗口 cwnd 缓慢地增大,即每经过一个往返时间 RTT 就把发送方的拥塞窗口 cwnd 加 1,而不是加倍,使拥塞窗口 cwnd 按线性规律缓慢增长。
快重传
发送方只要一连收到三个重复确认,就知道接收方确实没有收到报文段,因而应当立即进行重传(即“快重传”),这样就不会出现超时,发送方也不就会误认为出现了网络拥塞。
快恢复
当发送端收到连续三个重复的确认时,由于发送方现在认为网络很可能没有发生拥塞,因此现在不执行慢开始算法,而是执行快恢复算法 FR (Fast Recovery) 算法:
(1) 慢开始门限 ssthresh = 当前拥塞窗口 cwnd / 2 ;
(2) 新拥塞窗口 cwnd = 慢开始门限 ssthresh ;
(3) 开始执行拥塞避免算法,使拥塞窗口缓慢地线性增大。

