TCP协议理解

简介 

关于TCP协议早就想开一篇文章了,但是一直有其他事拖着,这次干脆直接开个计算机网络栏位来好好整理一下。 

正文

紧接着上一篇HTTP协议理解,我们将数据经过HTTP打包后之后,也通过DNS查到了IP,这时候我们就需要将数据包发出了。这时候TCP协议就登场了。

那么TCP协议又做了哪些事情呢?主要可以分为以下几点:

  1. 发送前三次握手确定发送目标
  2. 分包
  3. 超时重传
  4. 滑动窗口发送包
  5. 拥塞控制
  6. 校验
  7. 发送结束四次握手断开链接

我们一条条来看看,首先从出名的三次握手开始,大致流程图如下:

首先客户端先发送SYN包,什么是SYN包呢?SYN包就是tcp发包的一种包的类型,不同的包类型有着不同的作用。

SYN包的作用就是希望建立连接

TCP的包类型是通过TCP首部的控制位决定的,就是下图被框起来的部分:

控制位一共有8个bit,详情如下图。

 控制位

每个位置的功能会在后续讲解中逐步提及,现在我们继续回到三次握手。

SYN包在发出的同时会初始化序列号,就是下图被框起来的32bit长度的字段

服务端在接收到SYN包后,会做出回应,根据包内的端口号和地址号(IP首部信息)发送ACK包

ACK包的作用就是做出回应,TCP协议要求除了SYN包外,其他所有包都应该将控制位的ACK位置设为1

在ACK包中也会有自己的序列号,同时会将客户端传来的序列号+1设置在确认应答位。

为什么要有两个序列号呢?这样的做的目的是为了区分客户端发包的顺序,和服务端响应的发包顺序。防止包乱序,以及请求和响应包序列冲突。

客服端接收到服务端的响应后,就不再发送SYN包了,而是发送ACK包完成最后一次握手。所以说只有在(客户端和服务端)建立请求的第一次发包才发SYN包。而服务端的SYN包会设置ACK值为1.

接下来都是发送ACK包,不断的互换自增序列号和确认应答号。通过这种方式进行网络数据传输,直到四次握手结束链接。

这里有一个小问题,为什么建立连接要进行三次握手,两次握手或者四次握手不行吗?

第一次握手是检验发送端的发送能力是否正常

第二次握手是检验接受的的接受能力和发送能看是否正常

第三次握手是检验发送的的接受能力是否正常

因此要进行三次握手,既保证了消息传递的可靠性,也最大限度的节约的网络资源。


以上就是三次握手的全部流程,握手结束后,就要开始进行分包。

为什么要分包?

原因是在复杂的网络环境中,每个目的主机和源主机接收信息的能力有限,如果发送的数据包大于计算机的接收能力,就要对发送的数据包进行分包处理。

那么分多大的包是如何计算出来的呢?

MSS值通常设置为外出接口上的MTU长度减去固定的IP首部和TCP首部长度,

MSS=MTU-20-20 注:第1个20是IP首部长度;第1个20是TCP首部长度

例:以太网的MTU为1500字节,则主机在建立TCP连接时通报的MSS是1460字节;
1500-20-20=1460

两台计算机通信时,如何确认最终最大消息长度呢?

这个确认过程是在三次握手环节进行的。如下图所示:

 发送端主机在发送SYN包时,会在TCP首部的选项字段设置发送端的MSS值

接收端接受到SYN包后,会在ACK包中同样的选项字段中设置接收端的MSS值

发送端接收到AKC包后,会选择两个MSS值中最小的一个值,加入到三次握手中最后一次握手的选项字段中,这样一来发送端和接收端双方都确定了相同的MSS值。


分包之后就可以开始发包了,每次发包都是由发送端发包,附上对应的序列号(不记得的同学可以回去看看三次握手),接收端接收到数据包后,如果校验没有问题,则会返回一个ACK包。这就完成了一整个发包的动作。

如果在这过程中出现了丢包,则会重新发包,一般Unix和Windows系统最开始判断丢包的时间是0.5s,如果继续丢包,则这个判断等待时间就会呈指数函数增长,2,4,8倍……

当然这个超时重传机制不可能无限次的等待,一般设置为6s,如果超过这个时间,就会判断网络出现异常,停止重传。


如果每次发包都需要等待接收端响应再发送下一个包的话,那么发送的速率则会非常的慢,虽然这样可以确保包有序。

因此,为了提高发包的效率,TCP协议采取的窗口的方式进行发包。

例如一个窗口的大小是4,那么每次发送端就不需要发送一个包再等待响应,而是会发送一个窗口单位的数据包,即同时发送4个数据包,这样做大幅的缩短了数据传输时间。如下图所示:

这样数据包的传输都会随着窗口的不断向下移滑动依次批量发送,这种方法被称为滑动窗口


可是,这种方法虽然提高了数据包的传输效率,但是却也带来了其他的问题。

问题一

假如同时发送四个数据包中,其中有一个数据包丢包了,那么另外三个数据包收到的ACK包序号都会是丢包的序列号+1

这时候,之前发过的4个数据包就会都被接收端丢弃,发送端会重新发送相应数据包。如下图所示:

这就是在窗口发送环节,针对丢包的高速重发控制

问题二

如果当前网络处于通畅的情况下,那么同时发送4个数据包并不能很好的利用这个网络的传输资源。

如果当前网络处于拥塞的情况下,那么同时发送4个数据包则会出现发不出去的情况,导致一直超时重传,加剧网络的拥塞。

因此,针对上述两种情况,提出了流量控制的概念。

我们的目的是希望窗口的大小可以随着网络的变化而变化。

那么谁最清楚窗口大小应该怎么设置呢?答案毋庸置疑是接收端服务器最清楚。

接收端会将自身缓冲区的大小放入TCP报文首部的窗口大小字段。这个数字越大,说明网络吞吐量越高。

ps:吞吐量计算公式如下:

 

当缓冲区即将溢出的时候,窗口大小的值也会设置为一个更小的值传给发送端,从而达到窗口大小控制的效果。

当发送端出现重发超时的现象,发送端会发送一个窗口探测包,用来获取接收端的窗口大小。

问题三

有了流量控制之后是不是就高枕无忧了呢?我们来看看以下的场景:

接收端当前的窗口大小是4,同时有两台主机访问接收端,接收端将自身窗口大小同时发给两台主机。两台主机同时发送窗口大小为4的数据包,接收端一下子就接收了窗口大小为8的数据包,从而导致缓冲区溢出,造成拒绝访问。

因此,在最开始网络通信之时,发送端并不会一下子就发送窗口大小的数据包,而是从1个数据包开始发送,然后呈指数化的增长。这就是所谓的慢启动

当然,指数化的增长并不是无限制的,也许增长到4个数据包大小的时候,就会发生网络拥塞。这时发送方会重新从1个数据包开始发送数据,同时将慢启动阈值设置为触发网络拥塞的值的一半——2。

当发送方的窗口大小重新通过指数化增长到刚刚设置的慢启动阈值(2)时,改为线性增长,每次增长数为:一个数据包的字节数^2/拥塞窗口字节数。

线性增长也不可能是无限增长的,当收到重复应答时,窗口大小会变成当前窗口一半+3的大小,同时慢启动阈值或变成当前窗口一半大小,然后继续线性增长,直到超时重新从0开始

当遇到拥塞情况时,会将TCP头部的控制位CWRECE设为1,通知对面将拥塞窗口缩小。


发包之后,接收端需要对收到的包进行校验,判断收到的包是否完整有序

TCP校验和是一个端到端的校验和,由发送端计算,然后由接收端验证。其目的是为了发现TCP首部和数据在发送端到接收端之间发生的任何改动。如果接收方检测到校验和有差错,则TCP段会被直接丢弃。

TCP校验和覆盖TCP首部和TCP数据,而IP首部中的校验和只覆盖IP的首部,不覆盖IP数据报中的任何数据。

TCP的校验和是必需的,而UDP的校验和是可选的。

TCP和UDP计算校验和时,都要加上一个12字节的伪首部

校验流程:

发送方:原码相加 ,并将高位叠加到低位,取反 ,得到反码求和结果,放入校验和
接收方:将所有原码 相加,高位叠加, 如全为1,则正确 

校验和的计算方式:

  1. 首先将检验和置零;
  2. 然后将TCP伪首部部分,TCP首部部分,数据部分都划分成16位的一个个16进制数
  3. 将这些数逐个相加,记得溢出的部分加到最低位上,这是循环加法: 0xc0a8+ 0x0166+……+0x0402=0x9b49
  4. 最后将得到的结果取反,则可以得到检验和位0x64b6

 


发包结束后,需要断开连接,但是这也不是说断就断的。TCP协议是通过四次握手实现断开连接的。先来看看流程是怎么样的。

  1. 首先客户端先发送FIN包,这也是一种包的类型,由控制位决定。
  2. 接受端收到FIN包后会回复一个ACK包,表示收到了请求断开的请求。
  3. 等所有缓冲区数据全部发送完,接收端才会再回复一个FIN包,提出断开请求。
  4. 发送端接收到之后也会回复一个ACK包。由此双方断开连接。

总结

以上就是TCP协议在网络传输中发挥的主要作用,当然还有一些知识点没有涵盖,

  1. 比如8个控制位这里只提到了5个:SYN,ACK,CWR,ECE,FIN。还有3个:URG,PSH,RST未提及。
  2. 还有TCP首部的紧急指针和选项字段中有哪些可选项也未提及,只讲到其中一个选项MSS
  3. 以及一些提高网络通信效率的算法,例如:Nagle算法,延迟应答,捎带应答等

这些如果各位感兴趣,可以另开一篇进行讲解。

以上就是对TCP协议的理解,如果有不对的地方,欢迎各位进行指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值