目录
前言
首先,我们需要了解TCP协议是工作在传输层的,实现了进程到进程的通信。同时相比于UDP,TCP增加了可靠性。
一、TCP协议段格式
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位紧急指针:标识哪部分数据是紧急数据;
二、TCP可靠性的保证
1.确认应答机制
就是对于数据的接收方来说,有责任对接收到的数据进行确认应答,但是如果同时收到多份数据,如何知道应答的是那一份,这就需要对数据进行编号---序列号(sequence number)SN。
32位序列号:携带本次发送的数据编号,每个字节占用一个字节,序号的大小,就是发送数据的第一个字节序号。
假设初始的SN == 1
发送数据[asdf] SN = 1
第二次发送数据[dbgfgcdcs] SN = 5
32位确认号:表示这次发送的数据我都收到了,下一次我期待收到的第一个字节的编号(ASN)。
还是那个例子:
客户端发送:[erty] SN = 1
服务器端回应 ASN = 5 也就是表示我已经收到这四个字节的了,下一次希望从第五个收
所以客户端第二次发送数据[dbgfgcdcs] SN = 5
这里服务器回应的TCP的包头了还包含了ack = 1,来表示这是一个确认段。
在上述的通信中,TCP维护着各自的SN。
2.超时重传机制
主机A发送数据给主机B之后,可能因为网络拥堵等原因,数据无法到达主机B; 如果主机A在一个特定时间间隔内没有收到B发来的确认应答,就会进行重发;但是,主机A未收到主机B发来的确认应答,也可能是因为B发送的ACK丢失了;因此主机B会收到很多重复数据。那么TCP协议需要能够识别出那些包是重复的包,并且把重复的丢弃掉。这时候我们可以利用前面提到的序列号,就可以很容易做到去重的效果。
上述不可能无限制的重传,所以对于多久后超时重传,以及最大的超时时间有了一些设计。
1.Linux中(BSD Unix和Windows也是如此),超时以500ms为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。
2.如果重发一次之后,仍然得不到应答,等待 2*500ms 后再进行重传。
3.如果仍然得不到应答,等待 4*500ms 进行重传。依次类推,以指数形式递增。
4.累计到一定的重传次数,TCP认为网络或者对端主机出现异常,强制关闭连接。
3.连接管理
首先要清楚:
1.TCP需要发送缓冲区:因为发送数据之后不可以立即丢弃,可能需要重传,所以要有可以保存到的地方。
2.TCP有接收缓冲区
3.TCP维护自己发送时的序列号,才可以用于填充发送时的SN字段;TCP维护已经接收数据的序号,才可以去重。
所以在TCP协议栈中就引出来了连接的概念,如下图所示:
那么为什么要设计TCP建立连接:
1.首先,必须确保对方的存在,才可以可靠的传输
2.交换一些必要的数据,比如SN、接收窗口的大小。
3.三次握手建立连接、四次挥手断开连接。
4. 流量控制
接收端处理数据的速度是有限的。如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等等一系列连锁反应。
因此TCP支持根据接收端的处理能力,来决定发送端的发送速度。这个机制就叫做流量控制---滑动窗口机制(Flow Control)。
1.接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 "16位窗口大小" 字段,通过ACK端通知发送端;
2.窗口大小字段越大,说明网络的吞吐量越高;
3.接收端一旦发现自己的缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送端;
4.发送端接受到这个窗口之后,就会减慢自己的发送速度;
5.如果接收端缓冲区满了,就会将窗口置为0;这时发送方不再发送数据,但是需要定期发送一个窗口探测数据段,使接收端把窗口大小告诉发送端。
流量控制---滑动窗口实现的模拟图:
这个滑动窗口机制的每一个阶段的状态:
5.拥塞控制
虽然TCP有了滑动窗口这个大杀器,能够高效可靠的发送大量的数据。但是如果在刚开始阶段就发送大量的数据,仍然可能引发问题。
因为网络上有很多的计算机,可能当前的网络状态就已经比较拥堵。在不清楚当前网络状态下,贸然发送大量的数据,是很有可能引起雪上加霜的。
TCP引入慢启动机制,先发少量的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据。
此处引入一个概念程为拥塞窗口:发送开始的时候,定义拥塞窗口大小为1;每次收到一个ACK应答,拥塞窗口加1;每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口(流量控制里的窗口)大小做比较,取较小的值作为 实际发送的窗口。
像上面这样的拥塞窗口增长速度,是指数级别的。"慢启动" 只是指初使时慢,但是增长速度非常快。
为了不增长的那么快,因此不能使拥塞窗口单纯的加倍。此处引入一个叫做慢启动的阈值当拥塞窗口超过这个阈值的时候,不再按照指数方式增长,而是按照线性方式增长。
如下图所示:
当TCP开始启动的时候,慢启动阈值等于窗口最大值;
在每次超时重发的时候,慢启动阈值会变成原来的一半,同时拥塞窗口置回1;
6.总结
对于连接管理、超时重传机制,是为了更好的让确认应答机制更好的发挥作用。同时,通过上述的讲解,我们可以总结出TCP连接的三个特点:
1.可靠性:可见TCP为了做到可靠性,设计了很多机制,来最大程度的保证数据的有序性以及正确性。
2.有连接: TCP需要经过三次握手建立连接,为了确保对方存在,保证数据传输的可靠性;以及同步一些必要的数据。
3.面向字节流: 对于数据来说,一次写的数据不一定是同时发的(放在发送缓冲区),由于流量控制等将数据分成流,所以,数据以字节流的方式发送。而UDP没有发送缓冲区,所以数据只可以以数据报的形式发送,也就是一次写的内容全部发送。
总结
加油哦!~~