【Linux网络】详解TCP协议(1)
小伙伴们大家好,本片文章将会讲解 TCP协议 的相关内容。
如果看到最后您觉得这篇文章写得不错,有所收获,麻烦点赞👍、收藏🌟、留下评论📝。您的支持是我最大的动力,让我们一起努力,共同成长!
文章目录
- `1. TCP 协议简介`
- ==<font color = blue><b>🎧1.1 TCP 协议段格式🎧==
- ==<font color = blue><b>🎧1.2 TCP 解包和分用🎧==
- `2. TCP 确认应答机制(ACK)和捎带应答`
- ==<font color = blue><b>🎧2.1 什么是确认应答机制🎧==
- ==<font color = blue><b>🎧2.2 TCP 通信模式🎧==
- ==<font color = blue><b>🎧2.3 捎带应答🎧==
- `3. 超时重传机制`
- ==<font color = blue><b>🎧3.1 超时重传发生的 2种 情况🎧==
- ==<font color = blue><b>🎧3.2 总结序号的 3个 作用🎧==
1. TCP 协议简介
TCP(传输控制协议
)是一个面向连接的协议,保证数据在网络中 可靠、顺序地传输
。它通过 建立连接、数据传输和断开连接
三个阶段来管理数据的传输过程。TCP 使用 确认机制、重传机制、流量控制和拥塞控制等技术
,以确保数据包的完整性和顺序。
-
连接建立:TCP 通过三次握手(SYN、SYN-ACK、ACK)建立连接,确保双方准备好数据传输。
-
数据传输:数据被分割成段,每个段都有序号和确认号。接收方确认每个段的接收,确保数据完整性。
-
流量控制:使用滑动窗口机制控制发送方的数据量,避免接收方溢出。
-
拥塞控制:通过算法(如慢启动、拥塞避免)调节发送速率,防止网络拥堵。
-
连接断开:通过四次挥手(FIN、ACK、FIN、ACK)关闭连接,确保数据传输完毕。
🎧1.1 TCP 协议段格式🎧
TCP 协议段格式简略图
TCP 协议段格式解释
- 源/目的端口号:表示数据是从哪个进程来, 到哪个进程去;
- 32 位序号/32 位确认号:后面详细讲;
- 4 位 TCP 报头长度:表示该 TCP 头部有多少个 32 位 bit(有多少个 4 字节);
- 每一位最大表示值为
权值 * 4
; - 所以TCP 头部最大长度是
15
∗
4
=
60
(
B
y
t
e
)
15 * 4 = 60(Byte)
15∗4=60(Byte);
- 每一位最大表示值为
- 6 位标志位:
- URG:紧急指针是否有效;
- ACK:确认号是否有效;
- PSH:提示接收端应用程序立刻从 TCP 缓冲区把数据读走;
- RST:对方要求重新建立连接;我们把携带 RST 标识的称为复位报文段;
- SYN:请求建立连接; 我们把携带 SYN 标识的称为同步报文段;
- FIN:通知对方, 本端要关闭了, 我们称携带 FIN 标识的为结束报文段。
- 16 位窗口大小:后面再说;
- 16 位校验和:发送端填充, CRC 校验。接收端校验不通过, 则认为数据有问题. 此处的检验和不光包含 TCP 首部, 也包含 TCP 数据部分。
- 16 位紧急指针:标识哪部分数据是紧急数据;
- 40 字节头部选项:暂时忽略。
🎧1.2 TCP 解包和分用🎧
我们可以从四位首部长度中知道 TCP
首部长度是多少:
-
假设首部长度是
0011
表示的二进制位,即 3 3 3,那么首部长度就是 3 ∗ 4 = 12 ( B y t e ) 3 * 4 = 12 (Byte) 3∗4=12(Byte); -
如果首部长度是
1111
表示的二进制位,即 15 15 15,那么首部长度就是 15 ∗ 4 = 60 ( B y t e ) 15 * 4 = 60(Byte) 15∗4=60(Byte);- 如果总长度
大于 20Byte
,说明要在选项中读取首部长度 - 20 字节
- 如果总长度
-
类似地,如何反向计算出对应的二进制位呢?假设头部长度是
28 Byte
:- x ∗ 4 = 28 x * 4 = 28 x∗4=28 解得 x = 7 x = 7 x=7;
- 7 有二进制表示解释
0111
; - 所以首部长度就是
0111
。
2. TCP 确认应答机制(ACK)和捎带应答
🎧2.1 什么是确认应答机制🎧
在上图中,假如 主机A 要给 主机B 发送信息,那么怎么保证 主机B 收到了信息呢?
- 那么 主机A 肯定是要收到 主机B 的应答,就表明 主机B 收到了信息;
- 因此在报头中就存在一个标志位
ACK
表明我发送的这一条信息是应答。 - 如果 主机A 没有收到消息就说明数据丢包了。
- 这里没收到消息可能有两种情况,主机A 发送给 主机B 的时候就发生了丢包;
- 还有一种情况就是 主机B 确实收到了 主机A 的消息并且发送了
ACK
给主机A,但是返回信息的过程中数据丢包了; - 这两种情况统一成 主机A 未收到
ACK
就为丢包。
32位序号和确认序号
当发送数据的时候,发送方会用到序号,当接收方接收到数据发送ACK
的时候,会用到32位序号,那么什么是序号和确认序号呢?
- 实际上我们可以将
TCP
的发送缓冲区和接收缓冲区假想成数组,这样就每个数据就天然有了一个下标,而发送方的序号就是要发送数据的最后一个下标; - 类似地,接收方发送
ACK
的时候也会有确认序号了,默认情况下确认序号等于序号加1;- 因为确认序号的定义是告诉发送方这个序号之前的所有数据我都已经接收到了;
- 告诉发送方下一次发送要从哪个序号开始发送。
🎧2.2 TCP 通信模式🎧
通信方式1:
通信方式2:
- 上面两种方式是 TCP 常见的通信方式,一个是每次发一条数据然后等待应答,收到应答之后再发送数据;
- 另一种方式是一次发送多次数据,然后等待接收方发送多次应答(这种方式下一篇文章会详细说明)
🎧2.3 捎带应答🎧
为什么要有两个序号
很多人可能有一个问题,就是为什么报头种要同时拥有序号和确认序号,如果只有一个序号,不是同样可以告诉发送方某个序号之前的所有数据接收方都已经接收到了,并提醒发送方从下一次从哪个序号开始发送吗?
这里先说一点:
- 首先因为 TCP是支持全双工 的,如果接收方除了想发送
ACK
,还想发送正文数据,就需要序号和确认序号了。- 发送
ACK
需要确认序号; - 发送正文数据就需要序号了。
- 发送
我们把这种应答方式叫做 捎带应答。
3. 超时重传机制
🎧3.1 超时重传发生的 2种 情况🎧
- 主机 A 发送数据给 B 之后, 可能因为网络拥堵等原因, 数据无法到达 主机 B;
- 如果 主机 A 在一个特定时间间隔内没有收到 B 发来的确认应答, 就会进行重发;
但是, 主机 A 未收到 B 发来的确认应答, 也可能是因为 ACK
丢失了:
- 如果是这种情况,接收方就会接收到很多的重复数据,所以 TCP 就需要认识这些重复的数据,并且把重复的丢弃掉;
- 这时候我们可以利用前面提到的序列号, 就可以很容易做到去重的效果;
那么, 如果超时的时间如何确定?
- 最理想的情况下, 找到一个最小的时间, 保证 “确认应答一定能在这个时间内返
回”; - 但是这个时间的长短, 随着网络环境的不同, 是有差异的;
- 如果超时时间设的太长, 会影响整体的重传效率;
- 如果超时时间设的太短, 有可能会频繁发送重复的包。
TCP 为了保证无论在任何环境下都能比较高性能的通信, 因此会动态计算这个最大超
时时间。
Linux
中(BSD Unix
和Windows
也是如此), 超时以500ms
为一个单位进行控制, 每次判定超时重发的超时时间都是500ms
的整数倍;- 如果重发一次之后, 仍然得不到应答, 等待
2*500ms
后再进行重传; - 如果仍然得不到应答, 等待
4*500ms
进行重传。 依次类推, 以指数形式递增; - 累计到一定的重传次数, TCP 认为网络或者对端主机出现异常, 强制关闭连接。
🎧3.2 总结序号的 3个 作用🎧
- 构建确定序号(一般是序号加1);
- 接收方的去重操作需要用到序号;
- 保证发送方的数据按需放到接收方的缓冲区中。