可靠传输两种机制
- 确认应答: 解决数据是否发过去以及数据顺序是否正确问题
- 超时重传: 解决数据发送过程中丢包,发送方迟迟拿不到应答报文问题
TCP协议
TCP 传输控制协议. 对数据的传输进行详细的控制
长啥样?如下:
常用项解释:
- 源/目的端口: 表示数据从哪个进程来,到哪个进程去
- 32位序号/32位确认序号: 表示数据顺序
- 4位TCP报头长度: 表示该TCP头部有多少个32位bit(有多少个4字节)
- 6位标志位:
- URG: 紧急指针是否有效
- ACK: 确认号是否有效
- PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走
- RST: 对方要求重新建立连接;把携带RST标识的称为复位报文段
- SYN: 请求建立连接;把携带SYN标识的称为同步报文段
- FIN: 关闭连接;把携带FIN标识的称为为结束报文段
- 16位紧急指针: 标识哪部分数据是紧急数据
对于标志位来说: 默认为0.当标志位为1(例如SYN = 1)的时候表示此次是请求连接报文.
确认应答
情景带入: 现在有两个人(A,B). A和B进行商量去吃饭(要不要吃饭,吃什么饭).
确认数据是否发送过去
在上述情景中,当 A 给 B 发送消息,那么 A 如何知道 B 收到了消息?
即 应答报文(ACK报文).也就是消息发送过去后,会返回一个应答报文.
如下:
数据顺序是否正确
A 给 B发送了两条消息, B 分别对两条消息进行回复.那么如何知道 B 具体是回复了哪个消息呢?
如上图,若 “不知道!” 先传输到 A 这边, 此时 A 就会误解 B 的意思.为了解决上述问题, TCP 就针对数据进行编号
- 给发送的消息分配一个序号(放到32位序号里面)
- 应答报文会有一个确认序号(放到32位确认序号里面)
具体做法: TCP 将每个字节的数据都进行了编号。即为序列号
- TCP 针对字节来进行编号的,没有一条消息两条消息的说法.
对于序号的理解:
- 接收方的序号和发送方的序号无关(不是说发送方的序号是啥,确认序号就是啥)
- 确认序号取的是发送方发过来的所有数据中最后一个字节的下一个字节的序列号
如下图:
如何确认多个序号的顺序呢?
- 对多个序号的顺序,就会由TCP自己来进行整队.
- TCP 会有一个接收缓冲区(一块内核中的内存空间),每个 socket 都有一份自己的缓冲区
- TCP 按照序号针对收到的消息进行整队
基于上述机制,对于应用程序来说,读取的数据一定是和发送数据的顺序一致的.对于用户来说,就知道了消息是否被对方接收到,保证这次连接的可靠传输
超时重传
上述情景中,若 A 对 B 发送的消息在传输过程中丢失了呢?
发送方对于丢失的判定:
- 一定时间内没有收到 ACK
丢失的两种情况:
- 发送方发送数据,数据在传输过程中丢失了,接收方没有收到数据,自然没有返回 ACK
- 接收方收到数据了,返回的 ACK 丢了
数据在传输过程中丢失
针对这种情况,只需要将数据进行重新传输即可.
当到达超时重传的时间数据会自动进行重传
返回 ACK 丢失
针对这种情况,若进行超时重传,数据就会重复出现,对于转账这类操作显然是不符合常理的.
TCP 的解决办法:
在 TCP 的缓冲区里面,会自动对那些相同序列号的数据进行去重,保证了应用程序读到的数据只有一份
若出现超时重传失败:
- TCP会再次进行超时重传,但是每丢包一次,超时等待的时间都会增加
- 连续重传多次,都无法得到ACK,TCP就会重置连接(即重连)
- 当重置连接也失败,TCP就会关闭连接,放弃网络通信