1.TCP协议段格式
16位相当于2个字节
32位序号表示给每个数据都进行了编号
32位确认序号指的是返回的如果是应答报文,这个应答报文的序号就是确认序号,如果不是应答报文,则是普通序号,跟上一点一样.
比UDP多了窗口大小,紧急指针,以及保留以及选项,这些都和TCP的特性相关
2.TCP的相关特性
1.确认应答
2.超时重传
重传数据,发送数据给对方时,对方没有返回ACK,中间有可能经历了数据丢包(比较校验和,如果校验和不一致会主动触发丢包)或者接收方出现了问题,所以这时发送方会等待一段时间后进行重传数据,
如果接受方收到两份一样的数据,会进行数据去重.
重传之后接受方也没有应答的话就会尝试重新连接
3.连接管理(最重要)
先建立连接(三次握手)
传输完毕后断开连接(四次挥手)
简化过程如上:三次握手时每次数据报文传输,都要经过一系列的封装分用,分成两个包来发,就比一个包代价大,但是四次挥手中间不能合并,因为中间的ACK返回是内核的行为,收到FIN后会立刻返回ACK,而FIN是用户代码行为,表示调用socket.close方法,才会触发FIN,所以两者之间会存在一定的时间间隔,无法同一时间传输.
建立连接的意义:确保双方的发送能力和接收能力正常,可以协商重要数据(建立连接后发送数据)
4.滑动窗口
上面的情景是处理一个请求对应一个响应,效率太低了
所以引入滑动窗口的概念,发送1-1000序号的数据时,返回一个
情况:1.会出现后发先至的情况,后发的数据会更早地被接收方接收
2.数据包到了,ACK丢了,这时如果1001丢了,但是2001到了,那么对于接收方来说1-1000和1001-2000序号的数据都是已经到了
3.数据包丢了,丢的数据包进行快速重传
5.流量控制
限制滑动窗口的重要机制
如果我们发送速率大于接收速率,这时就好比往水池里加水,如果流入的水多于流出的水则会水满则溢, 所以要让发送速率和接收速率一致才能稳定的传输,针对发送方,制约发送速率
如何衡量发送速率和接收速率的大小一致:
发送方:通过滑动窗口发送时窗口的大小衡量发送速率
接收方:接收缓冲区(阻塞队列),表示此时剩余空间的大小,应用层会调用inputstream.read()方法读取缓冲区的数据
流量控制就是通过接收缓冲区剩余空间的大小,来作为下一次发送时候的窗口大小.
上面TCP协议中16 位的窗口大小就是表示接收缓冲区剩余的空间大小,通过这个大小,用来制约发送速率
6.拥塞控制
流量控制是站在接收方的角度来制约发送方,实际上整体的传输中并不止这两个设备,还有一系列用来转发的设备
控制发送方的快慢,不光考虑B的接收能力,也要考虑中间设备转发能力
假设一个木桶的情景,一个木桶能装多少水,取决于最短的木板
流量和拥塞控制,都能影响发送方的速率(影响窗口的大小),在保证可靠性的前提下,尽量提高发送的速度,最终的滑动窗口的大小取决于流量控制和拥塞控制的较小值
拥塞控制的窗口大小要通过实验的方式,找出一个合适的窗口大小.
如果是拥塞的窗口大(发送方自己做实验),流量控制的窗口小(接收方通过接收缓冲区的剩余空间大小,通过ACK报文的报头,返回给发送方),说明中间设备的转发能力强,接收端慢
如果是拥塞控制的窗口小,流量控制窗口大,说明中间设备转发能力弱,接收端快
最终发送方的窗口大小(滑动窗口)取决于上述两者的最小值
7.延时应答
返回ACK时可以先等一会儿等到应用程序在缓冲区中读取一部分数据再返回,ACK不一定一一对应数据报,发送后面的确认序号会涵盖前面的确认序号
让流量控制别限制的太快,让接受缓冲区剩余空间变大
8.捎带应答
基于延时应答的策略,如果当延时传ACK和返回响应内容的时间重合了,这时就可以一起发送,减少了数据包传递的个数,减少了封装和分用的步骤
9.面向字节流
TCP面向字节流传输,但是仅仅体现在代码上,比如UDP的DatagramPacket,面向数据报传输
而TCP则是Socket面向字节流传输,但在传输层中两者都是以数据报文的形式传输,没有区别
但在接受缓冲区有一个问题:粘包问题
数据进入接收缓冲区后无法识别多个数据报中一份一份完整的应用数据(长连接),如果是缓冲区只有一个数据报只有一份完整的应用数据还可以
解决方案:
在应用层代码时,明确包之间的边界:1.使用分隔符.2.约定长度
3.总结
1.TCP协议 :有连接,可靠传输,面向字节流,全双工
2.TCP的相关特性:
确认应答:序号 确认序号
超时重传:重传数据
连接管理:三次握手,四次挥手
滑动窗口.可靠性前提下提高效率
流量控制.:接受方的处理能力(接受缓冲区的大小),
拥塞控制.中间节点的转发能力(通过实验的方式衡量)
上述两者都是对滑动窗口发送速率的制约
延时应答
捎带应答