推广 热搜: csgo  vue  angelababy  2023  gps  新车  htc  落地  app  p2p 

从建立网络连接到发送数据发生了些什么(1)

   2023-08-30 网络整理佚名2150
核心提示:当浏览器这类应用需要与服务端传输信息的时候会经历“三次握手”建立连接,经过这一阶段后就可以互相发送信息了。注意其中的SYN和ACK,在第一次发送时会把SYN的值写为1,理解为要建立连接,ACK为0。而客户端收到消息后发现SYN为1则知道连接建立成功,并再次向发送服务端消息,其中ACK写为1,因为服务端也需要确认刚才发送的消息已被收到。

当浏览器等应用程序需要与服务器传输信息时,会经过“三次握手”来建立连接。 过了这个阶段,就可以互相发送信息了。 对于连接的建立,通俗的说法就是可以想象在客户端和服务器之间建立一条通信管道来连接两者。 此声明是为了便于理解,

实际情况当然并非如此,而是发送者和接收者通过交换信息来改变各自当前的状态并确定下一步要做什么,从而达成默契。

就像我在微信上问你:你现在忙吗? 我现在的状态是和你聊天。

忙完后回答:你不忙了,你想对我说什么,可以开始说话了吗? 你现在可以和我聊天了。

我回答:好,那我接下来开始讲。

我们现在的状态是准备开始聊天,接下来我们会发送正式的聊天消息,而你也准备好接收消息和回复,这期间的状态会包括写消息、等待消息、崩溃和删除等等各种状态转换。 而且中间其实没有管道,而是通过交换信息来知道自己应该处于什么状态,接下来要做什么。

那么我们来看看真实的情况是什么样的呢?

首先,服务器处于监听等待通信状态。 客户端知道需要通信的服务器地址后,会发送数据包请求建立连接。 数据包包含要交换的信息,其中之一称为 TCP 标头。 它是TCP在传输信息之前附加的一条信息,其中包含“三次握手”的信息。 让我们看看里面有什么:

注意其中的SYN和ACK。 第一次发送时,SYN的值会写入1,表示要建立连接,ACK为0。服务器返回给客户端的报文中,SYN的值也写入1表示接受连接,ACK为1理解为确认收到刚才的消息。

客户端收到报文后发现SYN为1,就知道连接建立成功,再次向服务器发送报文,其中ACK写为1,因为服务器还需要确认该报文刚刚发送已经收到。

浏览器等程序发送的数据会首先被处理并分割成多个小数据包。 我们来看看他们是如何划分的:

其中,MTU是最大传输单元,表示一个数据包的最大容量,MSS是去掉包头后真正可以发送的数据容量。

在分割过程中,每条数据从头开始的位置都会被写入交换信息中,即TCP头的“序列号”,以便接收数据的一方判断是否有遗漏。 比如第一次发送的数据大小是100,初始序号是1,第二次发送的序号应该是101,如果是201,说明中间有遗漏。 如果确认无遗漏,接收方会将对方下次应发送的序列号值写入返回内容的ACK中(例如第三次应为201),返回给对方前一个发送者,并将交换信息中的ACK字段写为1,这是为了让对方知道这个包是用来告知ACK号的,需要检查ACK号。

在实际传输过程中,序列号的初始值不会是1,而是一个随机数,以防止预测和利用。 看一下ACK号和序列号的传输过程:

不过,数据的传输是双向的,服务器也会向客户端发送数据。 客户端计算初始序列号并将其与数据一起发送到服务器。 服务器收到后计算ACK号并返回。 服务器还需要计算自己的初始序列号并将其与数据一起发送给客户端,然后客户端得到ACK并将其返回给服务器。

这样,双方就告诉对方自己的初始序列号,并开始传输数据。 流程如图:

发送的数据会先保存在缓冲区中,当一定时间内没有收到对方的ACK号时,会重新发送数据。 但是,如果由于网络拥塞等原因导致ACK的返回延迟,而之前延迟的ACK在重传这些数据包之后才收到,就会被浪费。

那么问题来了,ACK的等待时间如何设置呢? 此时等待时间会动态调整,根据每次ACK返回的时间进行调整,如果ACK返回变慢则等待时间会延长。 等待ACK号的时间仍然可以利用,在等待时间内可以连续发送数据。 接收方将接收到的数据放入缓冲区,然后从缓冲区中取出数据进行组装和恢复。

那么问题又出现了,如果发送的数据过多超出了接收方的处理速度,就会导致缓冲区被填满,那么到底应该发送多少数据呢?

这时,上面提到的交换信息,即TCP头中的“窗口”字段就发挥作用了。 当接收方处理完数据并释放缓冲区空间后,就可以通过“窗口”告诉对方下次要发送多少数据。

这时候问题又来了,什么时候更新“”值合适呢?

可以想象,如果缓冲区有空间,就可以告诉对方发送数据,但同时考虑到ACK号是在确认数据正确之后才发送的,完全分离了两者可能会导致发送的数据包过多,所以可以将两者结合起来,当需要发送ACK号时,会延迟一段时间。 如果延迟期间有“窗口”更新,则会合并在一起发送。 如果连续发送多个ACK号,我们可以直接取出最新的ACK号与“窗口”更新一起发送,因为ACK号是用来根据接收到的数据量,只需要取最新的值即可,忽略之前的值,提高了效率。

从上面的内容可以看出,在传输过程中,双方通过不断交换信息来决定自己的行动,同时也存在很多状态的变化。 例如,在连接建立过程中,服务器一开始就处于监听状态。 对方ACK后,转向状态等等。

本文还有很多可以进一步挖掘的地方,比如如果初始序列号为1怎么使用,除了TCP头中的信息还需要用到哪些信息,以及发送数据的长度是否必须满足MSS发送等等。

过往亮点:

 
反对 0举报 0 收藏 0 打赏 0评论 0
 
更多>同类资讯
推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报
Powered By DESTOON