TCP详解

2021-03-20  本文已影响0人  CharlesCT

思考

在进入正文之前,我们先看看这些面试问的一些问题!
TCP和UDP区别?TCP报文是什么?TCP的三次握手?两次行不行?TCP的四次挥手?TIME_WAIT知道吗?
TCP为什么是安全的?TCP为什么会有黏包问题?

TCP特性

我们都知道TCP/UDP都是传输层的协议!这个一定需要知道,意思是它只负责传输,类似货车运东西。
基于TCP的应用层协议有那些呢?常用的基于TCP的应用层协议有 SMTP:(简单的邮件传输协议)HTTP ,Telnet,以及FTP(文件传输协议)都是基于TCP的。
基于UDP呢?SNMP:(简单的网络管理协议)TFTP:简单的文件传送协议,以及DNS:域名解析协议。
TCP是面向字节流的 ,具有可靠性,面向连接的这三个特性。我们从这三个特性来展开讨论

面向字节流

为什么是说TC平时面向字节流的呢


image.png

按照图示所描述的那样,我们在传输层的上面可能有很多的程序,它们都需要发起网络传输的服务,就拿经常使用的微信来说,我们平时发的都是文本,怎么到TCP是字节流了呢?
我们看看TCP的报文结构,在计算机的网络里面,报文就代表一次传输的数据。


image.png

我们看到在传输层,它是不知道这个数据要送往那个ip 的,但他会知道是目标端口和源端口。
不加上其他的数据TCP的一个报文头部数据就占了,20个字节,所以这也是TCP的一个缺点,报头占空间大。


image.png
可变选项

可变选项是TCP代表的内容可以有多种,比如扩大窗口


image.png

为什么说TCP是面向字节流呢?
TCP不会把应用层传递的内容一下子都都发送出去,因为网络是不稳定的,如果一旦发送失败就会造成大量的数据浪费。所以TCP会把应用层传递的内容,变成字节流,给他分段并且进行编号,分批发送。


image.png

可靠性

根据上面的TCP报文结构我们知道了,TCP会对每一个发送的包进行编号,这个编号在接收方在接受到一个数据包之后,会向发送方确认数据包,也就是我们上面看到数据包的 ACK标志位会被设置为1。
但是会出现一种问题,如果我发送的这个包接收方并没有收到或者它发送的ACK的这个数据包我也没有收到,出现了数据包丢失的情况。TCP为了保证数据的完整性它会采用超时重传机制,会在发送一个编号的包之后进行计时,如果在超时,便会重写发送这个数据包。所以接收方可能会收到两个相同序号的数据包,这时候需要根据序号来去重。
如果在发送方发送一个字段就开始等待ACK确认,这样的效率太低了,所以TCP会一下子发送一连串的数据包。但是也不能无限制的发送,我们知道接收方是有一个缓冲区的,他可能会受到内存,网络以及其他因素的限制,不可能随时都接受大量的数据。这时候TCP就引入滑动窗口的机制

image.png
快速重传机制

但这样发送连续窗口的时候,我们发生丢包的时候按照超时重传的机制会造成大量的数据冗余问题。TCP可以采用超时重传的机制来提高传输效率比如发送方 ,发送了 1,2,3,4,5,6,这么长串的数据包,报文段1成功接收并被确认ACK 2,接收端的期待序号为2!结果2因为某些原因没收到,3到达了,于是还是ack回2,后面的4和5都到了,但是还是ack回2,因为2还是没有收到,于是发送端收到了三个ack=2的确认,知道了2还没有到,于是就马上重转2。然后,接收端收到了2,此时因为3,4,5都收到了,于是ack回6。示意图如下:

image.png
但是为什么是三次ACK报文呢?
首先要明白一点,即使发送端是按序发送,由于TCP包是封装在IP包内,IP包在传输时乱序,意味着TCP包到达接收端也是乱序的,乱序的话也会造成接收端发送冗余ACK。这时候我们就要区分是乱序造成还是因为丢包引起的。
例如:我们发送 N-1 N N+1 N+2 一连串的报文
image.png
从以上罗列的情况可以看出,
在没丢失的情况下,有40%的可能出现3次冗余ACK
在乱序的情况下必定是2次冗余ACK
在丢失的情况下,必定出现3次冗余ACK
基于这样的概率,选定3次冗余ACK作为阈值也算是合理的。在实际抓包中,大多数的快速重传都会在大于3次冗余ACK后发生。
选择确认机制(SACK)

超时重传还是会有冗余的ACK报文出现,我们还可以在报文里面的选择的字段,添加需要重传的序号,减少冗余的确认报文。

网络拥塞

在网络世界里面传递数据是不稳定的,收到各种因素的影响。我们知道TCP发送方会根据接收方的缓存区的大小来调整自己的发送窗口。但是它是怎么确定这个大小的呢?

image.png
如果所示(这里的Y轴代表窗口大小,X轴代表传输的轮次)
TCP在网络拥塞的时候会遵循 四个特性:慢开始快恢复快重传拥塞避免

面向连接

TCP的连接是指的是:通信双方之间的记录,并不是真的去进行连接了 ,根据上面的可靠性我们可以知道,TCP是一个双工的通信,发送发可以给接收方发送报文,接收方也可以给发送方返回报文。它们都维护了一个缓存区,记录了双方的发送信息。
为了记录信息,TCP会经历握手的环节。

image.png ‘
服务器A向服务器B发送数据,则它会先经历握手。

断开连接,同样的TCP在断开连接的时候也会经历一些流程,也就是我们说的四次挥手。

image.png

还是上面的例子,服务器A要和服务器B进行断开连接的请求

这里我们可以解答开始的问题了,为什么要三次握手?
:因为TCP是双工的,建立连接的双方都可以向对方传递数据,如果只用两次握手只能保证单方的发送。比如A,B两次握手,B不向A发送ACK报文,B并不能保证它的数据一定能发送到A。

为什么要四次挥手?
:因为在对方发送FIN的时候只能代表对方没有数据传递了,但是接收方还有数据要向对方传递,所以在发送数据完了之后,再回复FIN字段,代表数据传输完毕可以关闭了。
为什么要由TIME_WAIT阶段:第一个原因是为了确保最后发送的ACK报文能传递成功,如果失败,我们在这个时间里面可以进行超时重传。第二个原因是为了保证后序因为超时重传的数据包都失效,不干扰下一次连接。
为什么会有黏包问题?
TCP是面向字节流,会把应用层传递的数据变成数据流,TCP不懂这些数据流的意义,他只知道从应用层拿到数据流,切割成一份份报文,然后发送给目标对象。而如果应用层传输下来的是两个数据包,那么极有可能出现这种情况:

image.png

粘包与拆包都是应用层需要解决的问题,可以在每个文件的最后附加上一些特殊的字节,如换行符;或者控制每个报文只包含一个文件的数据,不足的用0补充。

UDP

我们都知道TCP还有一个好兄弟,它就是UDP,UDP只实现了传输层的最小功能,他会给应用层传递的报文添加一个头部就交给下一层了,并没有做分包这样的控制。

头部

它的头部很简单,只包含以下字段:

优缺点

由于头部简单,也没有任何的控制措施,UDP具有以下缺点

但是由于没有这些机制的限制,UDP很放飞自我,它也有一些优点

UDP的适用场景

UDP适用于对传输模型需要应用层高度自定义、允许出现丢包、需要高效率的场景、需要广播;例如

上一篇 下一篇

猜你喜欢

热点阅读