Author:MTingle
major:人工智能
Build your hopes like a tower!
文章目录
文章目录
一. 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字节头部选项:暂时忽略;
• 6位保留位: UDP这个协议,长度受到两个字节的限制,想要进行扩展,发现扩展不了,一旦改变了报头的长度,就会使机器发送的 UDP 数据报和其他机器不兼容,无法通信, TCP 在设置报头的时候,就提前准备了几个保留位,使用保留位可以避免数据不兼容的问题.
二. TCP 特性
1. 确认应答(ack)
"确认应答" 是 TCP 用来确保可靠性最核心的机制!
并且 TCP中,还引入了序号和确认序号对于数据进行编号,在应答报文里告诉对方,我应答的是哪个数据,举个简单的例子来理解这个场景:
但如果网络中出现了先发后至的状况就会变成了以下这种状况,误会就发生了~
但当我们引入了确认序号之后,就能成功解决上面的这个问题~
以上是一个简化版本的模型,实际情况会更加复杂,TCP是以字节为单位进行传输的,所以TCP的序号和确认序号都是以字节来进行编号的.
假设载荷中有1000个字节,由1000个序号,由于序号是连续的,于是我们只需要在报头中存储第一个字节的信号,后续字节的序号都很容易计算得到
报头中的序号是1
主机B收到1 - 1000这些字节的数据之后,反馈一个应答报文,应答报文中的数据为1001,这个序号的意义就是:
1. < 1000的数据我已经收到了
2. 发送方接下来需要给我发1001的数据
2. 超时重传
如果传输过程中一切顺利,通过应答报文就可以告诉发送方,当前数据已经收到,凡是网络上可能出现丢包的状况,此时 ack 报文就无法让发送方收到了,此时我们就需要超时重传了.
发送方发送一个数据之后,进入等待,等待的时间里,收到了 ack(数据的传输需要时间),说明文件成功传输,若等了很久都没有收到 ack ,等待的过程有一个时间阈值,当超出了这个阈值后,此时发送方就会默认传出去的数据丢包了,此时,发送方就会把刚刚发出的数据包再传输一次.
网络上为什么会出现丢包
网络中的路由器 / 交换机要支持千千万万的主机进行通信,整个网络中,就可能存着某个路由器 / 交换机,某个时刻负载量很高,但是短时间内还有大量数据要经过这个设备转发,但是一台设备能够处理的数据量是有限的,很可能某个瞬间的高负载超出了这个设备能转发的数据的极限,此时多出来的部分就没了,这个情况下,就被设备丢包了.丢包的情况客观存在,什么时候丢包,难以预测.上面的过程中,认为没收到 ack 就是丢包了,其实这样的结论并不准确,也可能是数据没丢,传回发送方的 ack 数据包丢失了!
在情况二中,数据已经被 B 收到了,再传输一次同一份数据,B就会收到两次,那么这显然是有问题的,如果这个数据是扣款请求,那不是扣了对方两次钱吗!!!
针对这个问题, TCP socket 在内核中存在接收缓冲区(一块内核空间),发送方发来的数据,是首先要放到缓冲区当中的,然后应用程序调用 read/scanner.next 才能读到数据,这里的读操作实际上读的是接收缓冲区.
当数据到达缓冲区的时候,接收方首先会判定一下,这个数据是否在缓冲区,或是否在缓冲区存在过,如果在缓冲区或已经存在过,就会将这个数据丢弃,就会确保应用程序不会读到重复的数据.
接收方如何判断"重复数据"?<