一、TCP协议段格式
- 源/目的端口号:表示数据是从哪个进程来,到哪个进程去
- 32位序号:保证报文按序到达
- 32位确认序号:知道收到哪条信号,知道哪条报文丢失
- 4位TCP报头长度:表示该TCP头部有多少个32位bit位,所以TCP头部最大长度是15*4=60
- 6位标志位:URG:紧急指针是否有效;ACK:确认号是否有效;PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走;RST:对方要求重新建立连接,我们把携带RST标识的称为复位报文段;SYN:请求建立连接,我们把携带SYN标识的称为同步报文段;FIN:通知对方,本段要关闭,把携带FIN标识的称为结束报文段
二、多种机制
1.确认应答(ACK)机制
- TCP将每个字节分数据都进行了编号,即为序列号
- 每一个ACK都带有对应的确认序列号,告诉发送者,已经收到了哪些数据,下次从哪里开始发送
2.超时重传机制(可靠传输)
- 主机A发送数据给B之后,可能因为网络拥堵等原因,数据无法到达主机B;
- 如果主机A在一个特定时间间隔内没有收到B发来的确认应答,就会进行重发
- 主机A未收到B发来的应答,也有可能是因为ACK丢失了
- 如果此时进行重发,会使主机B收到重复数据,这时就需要TCP协议识别出哪些包是重复的包,并且把重复的丢弃掉(利用序列号,可以做到去重的效果)
超时时间的确定:
- 最理想情况下,找到一个最小的时间,保证“确认应答一定能在这个时间内返回”
- 但是这个时间的长短,随着网络环境的不同,是有差异的
- 如果超时时间设置太长,会影响整体的重传效率
- 如果超时时间设置太短,有可能会频繁发送重复的包
TCP为了保证在任何环境下较高性能的通信,会动态计算最大超时时间
- Linux中,超时以500ms为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍
- 如果重发一次后,仍然得不到应答,等待2*500ms后再次重传
- 如果仍然得不到应答,则等待4*500ms进行重传,以指数形式递增
- 累积到一定的重传次数,TCP认为网络或者对端主机出现异常,强制关闭连接
3.滑动窗口(效率问题)
- 滑动窗口大小指的是无需等待确认应答而可以继续发送数据的最大值(下面以滑动窗口大小为4000字节为例说明,每个段1000字节)
- 发送前四个段时,不需要等待任何ACK,直接发送
- 收到第一个ACK后,滑动窗口后移,继续发送第五个段数据,依次类推
- 操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区来记录当前还有哪些数据没有应答,只有确认应答过的数据才能从缓冲区删掉
- 窗口越大,则网络的吞吐量越高
4.流量控制(可靠性)
- 概念:TCP支持根据接收端的处理能力,来决定发送端的发送速度,这个机制就叫做流量控制
- 接收端将自己可以接收的缓冲区大小放入TCP首部的“窗口大小”字段,通过ACK段通知发送端
- 窗口大小字段越大,说明网络的吞吐量越高
- 接收端一旦发现自己的缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送端
- 发送端接收到这个窗口后,就会减慢自己的发送速度
- 如果接收端缓冲区满了,就会将窗口设置为0,这时发送方不再发送数据,但是需要定期发送一个窗口探测数据段,使接收端把窗口大小告诉发送端
5.拥塞控制
TCP引入慢启动机制,先发少量的数据,摸清当前的网络状态,再决定按照多大的速度传输数据
- 发送开始的时候,定义拥塞窗口大小为1(拥塞窗口:发送数据的数据量出现网络拥塞的值)
- 每次收到一个ACK应答,拥塞窗口加1
- 每次发送数据报的时候,将拥塞窗口和接收端主机反馈的窗口大小作比较,取较小的值作为实际发送的窗口
像上面的拥塞窗口增长速度是指数级别的;“慢启动”只是初始时慢,但是增长速度非常快
- 为了不增长的那么快,因此不能使拥塞窗口单纯的加倍
- 此处引入一个慢启动的阈值
- 当拥塞窗口超过这个阈值的时候,不再按照指数方式增长,而是按照线性方式增长
- 当TCP开始启动时,慢启动阈值等于窗口最大值
- 在每次超时重发的时候,慢启动阈值会变为原来的一半,同时拥塞窗口置回1