TCP

TCP

可靠传输是tcp最为重要的核心(初心)

可靠传输,并不是发送方把数据能够100%的传输给接收方

而是退而求其次

让发送方发送出去数据之后,能够知道接收方是否收到数据。

一但发现对方没有收到,就可以通过一系列的手段来进行补救



1.确认应答

确认应答就是用来判断接收方是否能够收到数据。

发送方,把数据发送给接收方之后,接收方收到一个数据之后就会返回一个应答报文。

发送方如果收到了这个应答报文就知道自己的数据是否发送成功了。

在网络中可能会出现一些信息丢失的情况如下

A先发给B一个咱们下午去吃自助餐,然后又发了一个咱们组队学习吧

B回应给好啊,又发送一个滚吧。

正常的情况下A收到回复明白了咱们下午去吃自助餐,但是不组队学习

但是不知道什么原因A先收到了滚吧,在收到好啊就理解为咱们组队学习下午不吃自助餐 。

这样收到的回应的顺序不同造成的误解很使人困扰。在实际的网络传输中就也有可能会出现这样的后发先致的情况(一个数据包在传输的过程中,走的路径可能是非常复杂的,不同的数据报走的不同的路线)。

TCP解决上述个问题需要完成两个工作

1.确认应答报文和发送出去的数据,能够对上号,不要出现歧义。

2.确保在出现后发先致的现象下,能够让应用程序这边仍然按照正确的顺序来理解数据。

TCP中的32位序号位和32位确认号位就会在发送信息时进行标记,然后如果出现后发先致,就让其等待至先发的到来。如下述例子

A先发给B一个咱们下午去吃自助餐(标记为1),然后又发了一个咱们组队学习吧(标记为2)

B回应给好啊(针对1的确认序号1),又发送一个滚吧(针对2的确认序号2)。

这样就通过序号了描述了数据的先后顺序。

此图只是粗略的形容了一下大概的工作流程实际中序号并不是按照这样一条两条来进行编号,而是按照字节来编号(TCP面向字节流)

 

如图所示,一个TCP包中一共有1000个字节的载荷数据。其中第一个字节的序号是1,就在TCP报头的序号字段中写1.

由于一共是1000个字节,最后一个就是1000,但是1000这样的数据并没有在TCP报头中记录。TCP报头中记录的序号,是这一次传输的载荷数据中的第一个字节的序号。其他字节的序号需要一次的推出。

在应答报文中就会在确认序号字段填写1001

因为收到的数据是1-1000,所以1001之前的所有数据,都被B收到了或者也可以理解为B向A要从1001开始的数据。

通过特殊的ack数据包,里面携带的”确认序号“告诉发送方,哪些数据已经被确认收到了.

此时发送方,心中就有数了,知道自己刚发的数据是到了还是没到。也就构成了可靠传输的核心部分。

TCP的初心是为了实现可靠传输  达成可靠传输的最核心的机制就是确认应答。

如何区分一个数据包是普通的数据还是ack应答数据?

如图所示

当ACK这一位为1时,表示当前的数据包是一个应答报文,此时该数据包中的确认序号字段就能够生效。

这一位为0时,表示当前数据包是一个普通报文此时数据包是一个普通报文。此时数据包中的确认序号字段是不生效的。

TCP这里的常见面试题:通过确认应答为核心借助,借助其他机制辅助,最终完成可靠传输。

不是三次握手四次挥手保证了可靠传输,这是建立连接的。

2.超时重传

确认应答,描述的是一个比较理想的情况

如果网络传输过程中,出现了丢包操作??怎么解决

发送方肯定就无法接收到ACK。

为什么会出现丢包??

网络如同现实生活中的公路一样,错综复杂,并且有很多的收费站

平常如果车流量不大的时候,车会很快通过收费站,很少出现堵车

但如果到节假日,收费站肯定会出现堵车

网络中的收费站可以理解为是一些路由器/交换机

如果数据包太多了就会在这些路由器/交换机上出现堵车

但是路由器针对堵车的处理往往粗暴,不会把这些积压得数据包都保存好,而是将其中得大部分数据包之间丢弃掉,这个数据包直接消失了在网络中。

丢包是一个随机得事情,在上述tcp传输过程中,丢包存在两种情况

1.传输的数据丢失了

2返回的ACK丢失了

发送方无法区分这两种情况,所以无论出现哪种情况发送方都会进行重新传输。

第一次是丢失了,重传一下试试,很大概率能传过去

假设丢包的概率是20%,两次都丢包的概率是4%,重传就大幅度的提升了数据会被传输过去的概率,重传操作是一个很好的丢包补救措施。

注:引入了可靠性,会付出代价。最明显的代价两方面

1.传输效率

2.复杂程度

发送方何时进行重传?等待时间(初始的等待时间是可以配置的。不同系统的时间不一定一样,也可以通过修改一些内核参数来进行改变时间,等待的时间也会进行动态变化,每多经历一次超时,等待时间都会变长)

发送方发出数据之后,会等待一段时间。如果这个时间之内,ack到达了,被视为数据到达。如果到达这个时间,数据还没到就会触发超时重传

例如

A->B发了一条数据,
第一次,A等待ACK的时间,假设是50ms

此时如果达到50ms,还没有ack,A就重传.
当A重传的数据,还是没有收到ack,第二次等待的时间就会比第一次更长
拉长也不是无限拉长,重传若干此时,时间拉长到一定程度,认为数据再怎么重传也没用了,就放弃 tcp连接(准确的说是会触发tcp的重置连接操作)


 

根据上图站在B的角度来看,收到了两条一样的数据,收到了重复的数据,是否会给程序带来一些bug,比如发一条,收的时候收到了两条一模一样的数据。

TCP帮我们解决了这个问题,TCP有一个接收缓冲区(内存空间),会保存当前已经收到的数据,以及数据的序号。接收方如果发现,当前发送方发来的数据,是已经在接收缓冲区中存在的(收到过重复的数据),接收方就会直接把后来这个数据给直接丢弃掉,确保应用程序读的时候,只能读到一条数据。

接受缓冲区不仅能进行去重,还能进行重新排序。确保发送的顺序和接受的顺序是一致的。

3.连接管理        

建立连接+断开连接

三次握手和四次挥手

tcp这里的握手,就是给对方传输一个简短的,没有业务数据的数据包,通过这个数据包,来唤起对方的注意,从而触发后续的操作。

握手这个操作,不是TCP独有的,甚至不是网络通信独有的,计算机中的很多操作,都会涉及到握手     

TCP的三次握手,TCP在建立连接的过程中,需要通信双方一共”打三次招呼“才能完成建立连接的。

A想和B建立连接,A就会主动发起握手操作,实际开发过程中,主动发起的一方,就是客户端,被动接受的一端就是服务器。

同步报文段,就是一个特殊的TCP数据包,没有载荷的(不携带业务数据的应用层数据包)

握手完成,A和B记录了对方的信息(构成了逻辑上的连接)。

建立连接的过程,其实是通信双方都要给对方发起syn,也要给对方反馈ack。一共是4次握手了,但是中间两个可以合并成一次。

        上图中的syn这一位为1表示这个报文段是同步报文段,如果是1不是同步报文段。

三次握手是要解决什么问题??


 

TCP初心,是为了实现"可靠传输”
进行确认应答和超时重传有个大前提,当前的网络环境是基本可用的,通畅的.
如果当前网络已经存在重大故障了,此时,可靠传输,无从谈起.

三次握手的核心作用一:
确认当前网络是否是通畅的

三次握手核心作用二:

要让发送方和接受方都能够确认自己的发送能力和接受能力均正常

三次握手核心作用三:
让通信双方,在握手过程中,针对一些重要的参数,进行协商
 

握手这里要协商的信息,其实是有好几个的。
大家要知道, tcp通信过程中的序号从几开始,就是双方协商出来的(一般不是从1开始的)
每次连接建立的时候,都会协商出一个比较大的,和上次不太一样的值.|


上图中的客户端应用层和服务器端应用层是操作系统原生socket api对应的执行过程

右侧TCP层的LISTEN等类似的都是服务器的状态,服务器这边的socket创建好并且把端口号绑定好,此时就会进入listen状态。此时就允许客户端来建立连接。ESTABLISHED是客户端和服务器都会有的状态。

注:
 

 

FIN叫做结束报文段。

建立连接一般都会是客户端主动发起的。

断开连接客户端和服务器都可以发起。

此时连接断开,这个时候就相当于A和B都把对端的信息删除了。

和三次握手不同的是这里的四次挥手不一定可以将中间的两次交互合二为一

不一定的原因在于ACK的触发时机和FIN的触发时机是不同的。

ACK是内核响应的。B收到FIN,就会立即返回ACK

第二个FIN是程序的代码触发的,B这边调用了close方法才会触发FIN

从服务器到收到FIN,同时返回ACK,在到执行到close发起FIN,中间的时间是不确定的。

像前面的三次握手,ACK和第二个syn都是内核触发的.同一个时机.可以合并.
这里的四次挥手,ACK是内核触发的,第二个FIN是应用程序执行close触发的.时机不相同,不能合并.


那是否意味着,如果我这边代码close没写/没执行到,是不是第二个FIN就一直发不出去??(有可能的)
如果是正常的四次挥手,"好聚好散”,正常的流程断开的连接.
如果是不正常的挥手(没有挥完四次),异常的流程断开连接.(也是存在的)

TCP中有一个机制延时应答,能够拖延ACK的回应时间。一旦ACK滞后了,就会有机会和下一个FIN合并在一起。

如上图如果哪一方主动断开连接,哪一方就会进入到TIME_WAIT

TIME_WAIT存在的主要意义,防止最后一个ACK丢失        

如果最后一个ACK丢失了,从右边来看,右边就会触发超时重传。

重新传送给左边FIN。

如果没有TIME_WAIT状态,就意味着左边这个时候已经进入到CLOSED状态,释放连接了。

此时重传的FIN没有人可以进行处理,没有人能返回ACK了,右边也永远收不到ACK,关闭不了了。

左边使用TIME_WAIT状态进行等待,等待的这个时间,就是为了处理后续右边可能重传的FIN

此时有重传的FIN来了,就可以正常返回ACK了。

右边的重传才有意义

TIME的等待时间???

假设网络上的两个节点通信消耗的最大时间为MSL(可自己配置的参数),

那么TIME_WAIT的时间就是2MSL(上限,绝大部分的数据包不会到达这个时间)

4.滑动窗口

TCP的可靠传输,会影响到传输的效率。因为多出来一些等待ack的时间,单位时间内能够传输的数据就变小了。

滑动窗口可以让可靠传输对性能的影响小一些。

TCP引入可靠机制导致传输效率是不可能超过没有可靠传输的UDP的。

TCP的效率机制都是为了尽可能减少两者之间的差距。

缩短确认应答的时间

如上图每收到一个应答报文,再发下一个数据,这个过程中,等待时间比较长。

如上图进行批量传输数据,不等待ack返回,直接在发下一个数据。

批量传输,也不是无限的进行传输。

存在一定上限,达到上限,统一等待ack。

不等待的情况下,批量最多能发多少个数据,这个数据量被称为窗口大小。

如上图

当前A->B是批量的发了四份数据.此时B也要给A回应四组ACK
此时A已经达到窗口大小,再收到ACK之前,不能继续往下发了.
需要等待有ACK回来了之后,才能继续往下发.
这里是怎么继续发的?
是等待四个ack都回来了,在继续发四条?

还是回来一个ack就继续发一个呢?
回来一个ack,就立即继续发一个.
 

相关推荐

  1. <span style='color:red;'>TCP</span>

    TCP

    2024-04-03 12:14:01      44 阅读
  2. <span style='color:red;'>TCP</span>/IP

    TCP/IP

    2024-04-03 12:14:01      56 阅读
  3. <span style='color:red;'>TCP</span>聊天

    TCP聊天

    2024-04-03 12:14:01      56 阅读
  4. <span style='color:red;'>TCP</span>通讯

    TCP通讯

    2024-04-03 12:14:01      53 阅读
  5. <span style='color:red;'>TCP</span>通讯

    TCP通讯

    2024-04-03 12:14:01      56 阅读
  6. <span style='color:red;'>TCP</span>通讯

    TCP通讯

    2024-04-03 12:14:01      58 阅读
  7. <span style='color:red;'>TCP</span>通讯

    TCP通讯

    2024-04-03 12:14:01      52 阅读
  8. <span style='color:red;'>TCP</span>通讯

    TCP通讯

    2024-04-03 12:14:01      52 阅读
  9. <span style='color:red;'>TCP</span>聊天

    TCP聊天

    2024-04-03 12:14:01      51 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-03 12:14:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-03 12:14:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-03 12:14:01       87 阅读
  4. Python语言-面向对象

    2024-04-03 12:14:01       96 阅读

热门阅读

  1. Docker入门

    2024-04-03 12:14:01       37 阅读
  2. Node.js入门:常用命令一览

    2024-04-03 12:14:01       30 阅读
  3. FPGA的串口的收发程序设计

    2024-04-03 12:14:01       41 阅读
  4. 每日2题(面试)2024.4.2

    2024-04-03 12:14:01       32 阅读
  5. 数学分析复习:等价量的概念

    2024-04-03 12:14:01       42 阅读
  6. RGB到Lab的转换原理及例程

    2024-04-03 12:14:01       37 阅读
  7. SQL简单优化思路

    2024-04-03 12:14:01       40 阅读
  8. docker 应用部署

    2024-04-03 12:14:01       37 阅读
  9. WebGL BabylonJ 如何改变相机移动方式(WASD移动)

    2024-04-03 12:14:01       34 阅读