Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >请求数据包从发送到接收,都经历什么?

请求数据包从发送到接收,都经历什么?

作者头像
SH的全栈笔记
发布于 2022-08-17 07:32:17
发布于 2022-08-17 07:32:17
8590
举报
文章被收录于专栏:SH的全栈笔记SH的全栈笔记

之前讲了「从输入 URL 再到浏览器成功看到界面」中的域名是如何变成 IP 地址的,了解了 DNS 相关的东西。这篇文章就聊聊发生在 DNS 解析之后的操作——建立连接。也就是我们常说的三次握手

看到三次握手你可能会说,这不是面试都被问烂了的题吗?

三次握手不就是:

  1. 服务器开始为 CLOSE 状态,然后监听某个端口,此时服务器会进入 LISTEN 状态
  2. 客户端最初也是 CLOSE 状态,客户端会向服务器发送一个带 SYN 标志位的数据包,主动发起连接。此时客户端会变成 SYN-SENT 状态
  3. 服务器接收到客户端的数据包之后,通过标志位判断出了客户端想要建立连接。然后返回一个 SYNACK ,此时服务器的状态变为了 SYN-RCVD
  4. 客户端收到了服务器的 ACK 之后,会回一个 ACK 给服务器,回完这个 ACK 之后,服务器的状态就变为了 ESTABLISH
  5. 服务器收到了客户端回复的 ACK 之后,服务器的状态也变成了 ESTABLISH

这不就完了吗?还有什么好聊的?

这篇文章不会涉及到上面提到的什么各种状态的变化,包内的标志位是什么,而是会更加关注于底层的东西,也就是上面那些发来发去的数据包是如何发送出去的

其实不仅仅是建立连接时的三次握手,像浏览器中调用的很多 HTTP 接口,都会和服务器进行通信。

那这些个请求到底都是怎么发送给服务器的呢?

这还用问?不就是发个 HTTP 请求就过去了吗?

当然,这个答案可能是很多不了解网络的人可能会说出的答案。

其实更具体、更准确的说法是通过协议栈网卡发送出去的。

其中,协议栈负责对数据进行打包,打包完成之后就由网卡将数据转换成电信号,通过光纤发送出去了。

网卡自不必说,用来和其他的计算机进行通讯的硬件,我们常说的 MAC(Medium Access Control) 地址,其实就是网卡的编号,从其被生产出来的那一刻就被确定的一个唯一编号。MAC 地址长为 48 个比特,也就是 6 个字节,用十六进制进行表示。

当我们知道了和我们通信的 IP 地址之后,就可以委托操作系统中的协议栈将来来自应用程序的数据,打包成数据包然后发送出去。那协议栈,具体是啥呢?协议栈其实是一系列网络协议的总和,例如:

  • TCP
  • UDP
  • IP

不同的应用程序在进行数据传输的时候,可能会选择不同的协议。例如我们使用的浏览器就是使用的 TCP 协议,而像之前讲过的 DNS 解析就用的 UDP 协议。

那数据在协议栈中到底经历了什么?才变成了一个一个的数据包?

就拿我们向服务器发送一个 HTTP 请求作为例子,我们知道 HTTP 请求中有:

  • 请求行
  • 请求头
  • 请求体

HTTP 是属于应用层的协议,而应用层还有很多其他的协议,每个协议所涉及到的数据也都不同,协议栈要怎么去兼容不同协议之间的数据呢?

答案是不做兼容。对于协议栈来说,所有的数据都只不过是一堆二进制序列

那协议栈收到了这一堆二进制序列之后是不是就直接交给网卡发送了呢?

我都这么问了,那显然不是了...

其实协议栈在收到数据之后并不会马上就会就发送出去,而是会先写入位于内存的 Buffer 中。那为啥不直接发出呢?

其实很简单,假设你现在正在公交车的起始站,你觉得公交车会来一个人就立马发车吗? 显然不是,它会等一段时间,有更多的乘客上车之后再发车。但是它又不能等太长的时间,不然后续站台的乘客就会等的很久。

协议栈之所以不立即发出去,其实也是同样的道理。其实这背后无非基础两种考虑:

  1. 数据的长度
  2. 等待的时间

应用层的程序发送过来的数据可能长度都不太一样,有的可能一个字节一个字节的发, 有的可能一次性就传入所有的数据。

如果收到数据就发送出去,会导致在网络中传输着很多小包,而这会降低网络传输的效率。

所以,协议栈在收到数据之后会等待一段时间,等数据达到一定量之后,再执行发送操作。

但是,协议栈又不能等的太久是吧?等太久了你让正在电脑面前操作的用户情何以堪,这种发送延迟会让用户体验刷刷的往下掉。

但是吧,想做到对这两者的平衡却不是一件简单的事。数据包太短,降低网络传输效率,等待太长时间,又会造成发送延迟。所以协议栈索性就把控制权交给了应用程序。

应用程序可以自己控制到底采取哪种措施,例如我们常用的浏览器,因为和用户实时的在进行交互,用户对整个页面的响应速度也相当敏感,所以一般都会采用直接发送数据的方式,即使其数据并没有达到「一定的量」

这一个「一定的量」到底是啥?

的确,上面都只说一定的量、一定的量,那这个量到底是多少?

要了解这个我们需要知道两个参数,分别是:

  1. MTU(Maximum Transmission Unit)最大传输单元
  2. MSS(Maximum Segment Size)最大分段大小

MTU 其实就代表了上面途中数据包的最大长度,一般来说是 1500 字节。而我们需要知道数据包是由以下部分组成的:

  1. 各种头部信息
  2. 真实数据

而从 MTU 中减去各种头部数据的大小,剩下的就是 MSS 了,也就是实际的数据。

知道了数据包的组成和 MTU、MSS 的概念之后,我们就可以继续接下来的步骤了。某次发送的数据,没有超过 MSS 还好,就可以直接发送出去了。

那如果超过了 MSS 咋办?例如我发这篇文章时所发请求的数据长度就可能超过 MSS 。

过长数据包拆分

此时就需要对数据进行拆分,按照 MSS 的长度为单位进行拆分,将拆出来的数据分别装进不同的数据包中。拆分好之后,就可以发送给目标服务器了。

TCP 会确保通信的服务器能够收到数据包。传输时对每个字节都进行了编号,举个例子,假设此次传输的数据是 1 - 1000 字节,然后服务器回的 ACK 就会是 1001,这就代表没有丢包

这些发送过的包都会暂存在 Buffer 中,如果传输的过程中出错,则可以进行重发的补偿措施。这也是为什么在数据链路层(例如网卡、路由器、集线器)等等都没有补偿机制,它们一旦检测到错误会直接将包丢弃。然后由传输层重发就好。

那要是网络很拥堵,服务器一直没有返回怎么办?

在服务器端,我们去和其他第三发进行交互时,是不是都会设定一个超时的时间?如果不设置超时时间那难道一直在这等下去吗?

TCP 也同理。客户端在等待服务器响应时,会有一个时间叫 ACK 等待时间,其实也是超时时间。

当网络发生拥堵时,其实你完全也可以把网络拥堵理解成路上堵车。此时,ACK 的返回就会变慢。如果返回时间长到了让客户端认为服务器没有收到,就有可能会重发。

并且有可能刚刚重发完,ACK 就到了。虽然服务器端可以通过序号来对包进行判重,不会造成错误,但是这种没有意义的重复包,在本身网络负担已经很重的情况下,你还往里怼重复的无用的数据包,这不是扯淡吗?这明显不行的。

那怎么避免上面的这个情况呢?答案很简单,稍微延长一点 ACK等待时间,这样一来就能一定程度上避免上述的问题。但是用屁股想想应该也知道,这个时间肯定不是越长越好,再长用户那又该等爆炸了。

除了网络波动会影响到 ACK 的返回时间,通信的物理距离也是一个影响的因素。说白了就是这玩意儿不可能设置一个固定的时间。所以,实际上,这个等待时间动态调整的,这次稍微返回慢了点,那我下次就稍微延长一点等待时间。返回 ACK 的速度如果很给力,那么就会相应的减少 等待

上面的概念也有一个大家很熟悉的名字,叫——超时重传

我们来设想一个更加极端的情况,假设你们通信的网线被挖断了,甚至机房起火了,这个时候无论你重发多少次都没用。那 TCP 不就一直无限循环的把请求发下去了?

当然 TCP 设计时也考虑到了这种情况,其在重传几次无效之后,就会强制中断通信,并抛出错误给应用程序。

问题又来了,客户端在向服务器发送数据包之后,等待 ACK 的过程中,真的就只是等 ACK,其他的什么也不做吗?

当然不是,这样极其的浪费资源,降低通信效率。发送完一个数据包之后,不用等待 ACK 的返回,会直接继续发送下一个包,这就是滑动窗口

但是这样会有一个问题,应用程序发送包发送的过于频繁,导致服务器接收不过来了。

因为刚刚说过,应用程序发送的时候,会将发送过的数据存储在 buffer 中。而对于接收方也是一样的,接收方收到消息之后,会将数据存储在 Buffer 中,然后在 Buffer 中对收到的数据进行重组,还原成最初的应用程序发送的数据。

但是如果发送的数据太快,超过了重组的速度,缓冲区就会被填满。而缓冲区一旦被填满,后续的数据就无法再接收了,然后丢包就出现了。

那 TCP 是如何解决这个问题的呢?答案是 流量控制。为了防止传输方发送的过快直接造成丢包,继而触发上面的超时重传机制,根据接收方的接受能力,来决定发送方的传输速度,这个机制就是流量控制

该机制作用于接受方。在TCP报文头部中会用一个16位的字段来表示窗口大小非常重要的调优参数。这个数字越大,则说明接收方的缓冲区越大,能够接收更多的数据。接收方会在确认应答的时候,将自己的剩余窗口大小写入,随ACK一起发送给发送方。

TCP流量控制

如果发送方接收到的大小为0,那么此时就会停止发送数据。这样会有一个问题,如果下一个应答(也就是窗口大小不为0)在过程中丢了,那么发送方就会进入死锁,相互等待。所以发送方会定期的向接收方发送窗口探测的数据段

好了,关于数据包的发送就介绍到这里。之后有机会再聊聊 TCP 的拥塞控制相关的东西。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 SH的全栈笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
协议栈——收发数据(拼接网络包,自动重发,滑动窗口机制)
1.发送方协议栈根据DNS提供的服务器ip端口确定和服务器通信使用的socket套接字, 填充tcp头部信息(发送接受方ip端口信息),将syn设置为1,修改当前socket状态为正在连接
小柔
2022/10/09
6710
协议栈——收发数据(拼接网络包,自动重发,滑动窗口机制)
Code For Better 谷歌开发者之声——协议栈收发数据(拼接网络包,自动重发,滑动窗口机制)
1.协议栈根据上层传递的服务器ip端口确定 要链接的服务器sicket, 填充tcp头部信息(发送接受方ip端口信息)并将syn设置为1,修改的socket状态为正在连接
魏铁锤
2022/10/27
3010
Code For Better 谷歌开发者之声——协议栈收发数据(拼接网络包,自动重发,滑动窗口机制)
收发数据的原理(下)
前言:网络知识非常的重要,如果你不是做程序的,那么一些网络常识还是得知道的;而做程序的,就更不用说了,不仅需要了解一些网络知识,还是知道其原理,如果不了解原理,不敢说他不是程序员,但是总缺了点意思,就像去北京没去过长城一样。
Dwyane
2018/12/28
1K0
《网络是怎么样连接的》读书笔记 - Tcp/IP连接(二)
套接字链接在表面上看就是建立连接,交换数据,断开连接,虽然实际上细节肯定没有那么简单,但是大体上的思路基本不变。
阿东
2022/06/20
7130
《网络是怎么样连接的》读书笔记 - Tcp/IP连接(二)
网络是怎样连接的 第一、二章 笔记
Request:Method + URI Response: Status Code + Header + Body + .......
MashiroT
2022/12/02
8630
超详细的Socket通信原理和实例讲解
关于对 Socket 的认识,大致分为下面几个主题,Socket 是什么,Socket 是如何创建的,Socket 是如何连接并收发数据的,Socket 套接字的删除等。
嵌入式Linux内核
2022/09/22
2.4K0
超详细的Socket通信原理和实例讲解
这篇文章带你读懂Socket,让你知道什么是Socket?
我们都知道,数据传输的方式有很多种。通常我们都是使用HttpClient 发起请求,传输JSON格式的数据。但是遇到数据量比较大的情况,或者需要传输比较大的XML报文时,可能就会用到Socket了。
跟着飞哥学编程
2022/11/30
6240
这篇文章带你读懂Socket,让你知道什么是Socket?
网络编程懒人入门(十四):到底什么是Socket?一文即懂!
本系列文章前面那些主要讲解的是计算机网络的理论基础,但对于即时通讯IM这方面的应用层开发者来说,跟计算机网络打道的其实是各种API接口。
JackJiang
2022/02/16
2.6K0
网络编程懒人入门(十四):到底什么是Socket?一文即懂!
探究!一个数据包在网络中的心路历程
想必不少小伙伴面试过程中,会遇到「当键入网址后,到网页显示,其间发生了什么」的面试题。
小林coding
2020/03/31
2.5K1
探究!一个数据包在网络中的心路历程
【网络协议】万文长篇,带你深入理解 TCP;场景复现,掌握鲜为人知的细节(上)
传输控制协议(TCP,Transmission Control Protocol) 是一种面向连接的、可靠的、基于字节流的传输层通信协议,由 IETF 的 RFC 793 定义;
sidiot
2023/08/31
2.7K0
【网络协议】万文长篇,带你深入理解 TCP;场景复现,掌握鲜为人知的细节(上)
硬不硬你说了算!近 40 张图解被问千百遍的 TCP 三次握手和四次挥手面试题
不管面试 Java 、C/C++、Python 等开发岗位, TCP 的知识点可以说是的必问的了。
小林coding
2020/05/18
7610
硬不硬你说了算!近 40 张图解被问千百遍的 TCP 三次握手和四次挥手面试题
Java程序员必须掌握的网站知识 —— TCP
本文主要通过整理网络上的资料,整理出的关于TCP方面的简单理论知识。作为Java程序员虽然更多的时候我们都是直接调用现成的API,但是对网络知识有个宏观的概念能方便我们更好的编写代码。当然,文中涉及的
tomas家的小拨浪鼓
2018/06/27
1.1K0
TCP、UDP、IP 协议分析
互连网早期的时候,主机间的互连使用的是NCP协议。这种协议本身有很多缺陷,如:不能互连不同的主机,不能互连不同的操作系统,没有纠错功能。为了改善这种缺点,大牛弄出了TCP/IP协议。现在几乎所有的操作
李海彬
2018/03/23
2.7K0
TCP、UDP、IP 协议分析
40张图揭秘,「键入网址发生了什么」
从上图可知,URL 中可以包含服务器的域名,文件的路径,收件人邮件地址,用户名,密码等信息。总之URL想表达的是:
我是程序员小贱
2020/08/18
6420
40张图揭秘,「键入网址发生了什么」
1万字30张图说清TCP协议
TCP(Transmission Control Protocol 传输控制协议)是一种基于IP的传输层协议,TCP协议面向连接、正面确认与重传、缓冲机制、流量控制、差错控制、拥塞控制,可保证高可靠性(数据无丢失、数据无失序、数据无错误、数据无重复到达)传输层协议。
网络工程师笔记
2021/05/17
1.2K0
1万字30张图说清TCP协议
网络拾遗之Socket
我们基本上从宏观角度描述了,应用层是如何构建通信消息、查询服务端IP地址的。今天,我们着重讲讲,在客户端准备好通信消息后,是如何委托OS的协议栈进行后续的处理。也就是,Socket如何处理从客户端拿到数据,并将其转发到协议栈。
前端柒八九
2022/08/25
3490
网络拾遗之Socket
网络是如何连接的?网络发展简介(四)
这一过程涉及宽带接入、浏览器、前端技术,DNS,TCP/IP,操作系统,网卡,驱动程序,传输设备,交换机、路由器,服务器等等网络、通信、web相关的几乎所有技术
noteless
2019/02/25
4K0
网络是如何连接的?网络发展简介(四)
Wireshark分析艺术【读书总结】
【统计->捕获文件属性】 Statistics -> Summary,查看文件属性信息,如平均速度、包大小、包数等等
Allen.Wu
2019/12/12
1.8K0
网络通信_知识点精讲
今天,我们继续「前端面试」的知识点。我们来谈谈关于「网络通信」的相关知识点和具体的算法。
前端柒八九
2022/12/19
3840
网络通信_知识点精讲
初识TCP,实验加抓包带你理解为什么需要三次握手、四次挥手
在前面的第二篇讲过一个通信的流程,里面提到了三种应用,HTTP、DNS、以及DHCP,这些呢,都是属于应用层的应用程序,正式因为越来越多的应用程序的出现,丰富了整个网络世界,对于学习路由交换数通技术来说,应用程序不是重点,特别对于新手来说,了解下常见的协议以及常见端口号的即可。而对于传输层来说,把TCP、UDP的特点、工作流程掌握,有个一定的认知,否则讲解的越多,对初学者来说会吸收不了,犯迷糊,建议是后续在随着知识点深入后,在回过头把TCP/IP协议框架看一次,你会发现又不一样的体会跟收获。
网络之路一天
2024/01/08
2280
初识TCP,实验加抓包带你理解为什么需要三次握手、四次挥手
推荐阅读
相关推荐
协议栈——收发数据(拼接网络包,自动重发,滑动窗口机制)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文