Linux网络:传输层协议TCP(一)

发布于:2024-07-27 ⋅ 阅读:(48) ⋅ 点赞:(0)

目录

一、TCP协议的定义

二、确认应答机制ACK

三、序号、确认序号

四、超时重传机制


一、TCP协议的定义

TCP 全称为 "传输控制协议(Transmission Control Protocol"). 人如其名, 要对数据的传 输进行一个详细的控制;

TCP 协议段格式

源/目的端口号: 表示数据是从哪个进程来, 到哪个进程去;

32 位序号/32 位确认号: 用于确认报文是否成功发送/接收。博主后面详细讲;

4 位 TCP 报头长度: 表示该 TCP 头部有多少个 32 位 bit(有多少个 4 字节); 所以 TCP 头部最大长度是 15 * 4 = 60

• 6 位标志位:

        服务器可能会同时收到各种各样的报文,通过标志位来判断收到的报文的具体类型,区分具体请求是什么。

         URG: 紧急指针是否有效

         ACK: 确认号是否有效

        ○ PSH: 提示接收端应用程序立刻从 TCP 缓冲区把数据读走

        ○ RST: 对方要求重新建立连接; 我们把携带 RST 标识的称为复位报文段

         SYN: 请求建立连接; 我们把携带 SYN 标识的称为同步报文段

         FIN: 通知对方, 本端要关闭了, 我们称携带 FIN 标识的为结束报文段

16 位窗口大小: 博主之后详谈

16 位校验和: 发送端填充, CRC 校验. 接收端校验不通过, 则认为数据有问题. 此 处的检验和不光包含 TCP 首部, 也包含 TCP 数据部分.

16 位紧急指针: 标识哪部分数据是紧急数据;

40 字节头部选项: 暂时忽略;

二、确认应答机制ACK

这里所谓发送的ACK和SYN不单单是建立连接和应答这一标志位,而是一个完整的报头,一个没有数据的纯报头,当要确认应答时,只需要将ACK改成1即可。而确认应答并不一定要单独发一个报头,可以将其和要发的数据一起发送,这也叫做捎带应答,比如中间的SYN加ACK就可以将其看作一次捎带应答。在日常的通信情况下,一般不会单独发送ACK,一般都是捎带应答,在发数据的同时也对对方做出应答。

结合下面序号和确认序号的部分,TCP发送的数据都有序号,一方发的数据序号假设位1-1000,那么另一方回应时确认应答就应该是1001,表示序号1000之前的数据全部收到了,接下来发的数据块的序号就应该从1001之后开始发。

三、序号、确认序号

TCP 将每个字节的数据都进行了编号. 即为序列号

TCP也叫面向字节流的协议,其通信双方都有发送缓冲区和接收缓冲区,所以将其要发送的数据想象成一个数组时,缓冲区中天然的每个字节都有序号,因为每个字节都有其对应的下标

所以在发送一次数据,收到对方应答后,下次再要发送数据的

新的序号=对方确认的序号+本次要发送的数据长度(如上图)

同样的,确认序号就是在接收到对方的序号后将ACK设置为1,下次再发给对方时,就是收到的对方的序号+1,比如上次对方发送数据为1001-2000序号的,那么这次要发送给对方的应答序号就是2001。

序号存在的意义:按序到达,应答和确认对应。

确认序号&&序号:两者都存在于TCP中的意义在于,同时向对方发送数据的同时,也同时在向对方做应答。(应答对方刚刚发的数据是否收到)

四、超时重传机制

主机 A 发送数据给 B 之后, 可能因为网络拥堵等原因, 数据无法到达主机 B;

如果主机 A 在一个特定时间间隔内没有收到 B 发来的确认应答, 就会进行重发;

结合上面的内容,如果主机A向主机B发送了数据,但是却一直没有等到对方发送过来对应的确认应答,也就是与刚刚发的序列号所对应的确认序列号,此时考虑到或许有特殊情况的发生,比如报文阻塞在某处没有到达对方主机,这时主机A会等待特定的时间,如果时间到了主机B依旧没有发送应答,那主机A就默认丢包了,直接再次发送刚刚的报文。

 

但没有收到应答并不一定是A主机没有发过去,也有可能是B主机收到了但是B主机的应答在发送过程中丢了,这时A主机再发消息,B主机就会收到一份一模一样的报文 。
那么 TCP 协议需要能够识别出那些包是重复的包, 并 且把重复的丢弃掉. 这时候我们可以利用前面提到的序列号, 就可以很容易做到去重的效果.

最理想的情况下, 找到一个最小的时间, 保证 "确认应答一定能在这个时间内返 回".

但是这个时间的长短, 随着网络环境的不同, 是有差异的.

如果超时时间设的太长, 会影响整体的重传效率;

如果超时时间设的太短, 有可能会频繁发送重复的包;

因为网络的情况是动态变化的,网速时快时慢,所以TCP 为了保证无论在任何环境下都能比较高性能的通信, 因此会动态计算这个最大超时时间.

Linux 中(BSD Unix 和 Windows 也是如此), 超时以 500ms 为一个单位进行控制, 每次判定超时重发的超时时间都是 500ms 的整数倍.

如果重发一次之后, 仍然得不到应答, 等待 2*500ms 后再进行重传.

如果仍然得不到应答, 等待 4 *500ms 进行重传. 依次类推, 以指数形式递增.

累计到一定的重传次数, TCP 认为网络或者对端主机出现异常, 强制关闭连接.