发送数据包
我们前面已经了解到为什么网络需要分层,每一层都有自己的职责。在发送数据包的过程中,这些层扮演着不同的角色。它们的主要任务是将数据包进行层层封装后发送,并在接收端逐层解封装。
就像下面的示意图所展示的那样,在部署在Linux服务器B上的服务端Nginx和Tomcat通过Socket监听着80和8080端口。这时,内核的数据结构(包括七层网络协议等)就会记录下这些信息。当有数据包发送到这两个端口时,内核就会将这些数据包转发给相应的进程。
在Linux服务器A上的客户端,如果打开一个Edge并连接到Nginx,同样通过Socket连接,客户端会被分配一个随机端口12345。同理,如果打开一个Chrome并连接到Tomcat,同样通过Socket连接,客户端会被分配一个随机端口12346。这些客户端的端口都是随机分配的,因为作为客户端,你只需要与其他人的服务器建立连接,而不需要一个固定的端口供所有人访问,因为你不是服务器本身。
在客户端上,当需要发送数据包时,通常会将请求封装成一个HTTP协议,并通过调用socket发送到内核。然后在传输层(即TCP层),会创建用于维护连接、序列号和拥堵控制的数据结构。在封装好的HTTP包的外层,还会再封装一个刚包装好的TCP头,然后继续传输到网络IP层。
在网络IP层,需要将目标IP和本机IP等信息封装在TCP包的外层,即在IP头中。随后,数据包会继续发送到数据链路层(即MAC层),这时需要将本机的MAC地址和目标MAC地址封装在IP包的外层,即在MAC头中。最后,数据包会被发送到硬件网卡,准备发送出去。需要注意的是目标主机的IP地址是用来确定数据包的目的地(也就是真实的目标服务器IP),而目标主机的MAC地址是用来确定数据包在局域网中的具体物理地址(可以认为是网关的MAC地址,并不是目标服务器MAC地址)。
终于发送的数据包准备好了,现在我们来详细讲述一下数据包在传输过程中发生的一些不为人知的事情。
当数据包到达交换机层,也被称为二层设备或MAC设备,因为它主要处理MAC层的操作。交换机不会改变数据包的MAC地址,而是会寻找目标MAC地址。就像图上标识的那样,交换机会检查数据包中的目标MAC地址,并根据自己的MAC地址表找到相应的端口,然后将数据包转发给对应的端口。如果交换机找不到目标MAC地址的对应端口,它会采取一种特殊的方式来解决问题,就像是在大声喊叫一样。交换机会发送一个广播帧,向所有连接的设备询问“这是谁的MAC地址?”这样,如果目标设备在网络上,它就会回复交换机,并告诉它自己的MAC地址。交换机将收到的回复信息更新到自己的MAC地址表中,以便将来能够更快地找到目标设备。如果交换机还是找不到目标MAC地址,那你看看是不是断网了吧,你可能已经脱离了互联网。
当路由器接收到数据包后,它会开始解析数据包的MAC头,并查看是否与自己的MAC地址匹配。如果匹配成功,路由器就会将数据包交给IP层进行处理。在IP层,路由器会根据数据包的IP头中的信息,在路由表中查找下一跳的信息,以确定应该从哪个网络接口发出去。在这个例子中,根据路由表的信息,数据包将会从右边的网络接口发出去。我们通常将路由器称为三层设备,因为它主要处理到第三层(即网络层)。实际上,路由器在转发数据包时会修改数据包的源MAC地址和目标MAC地址。
当从路由器右侧的网口发送出去的数据包到达网络2的交换机时,它将经历一次二层处理,并被转发到交换机右侧的网口。
最终,数据包将被转发到Linux服务器B。服务器B会检查数据包的目标MAC地址是否与自身匹配,如果匹配,则将MAC头部取下,并将数据包交给上一层。接下来,在IP层,服务器B会检查数据包的目标IP地址是否与自己匹配,如果匹配,则将IP头部取下,并将数据包交给上一层。在TCP层,服务器B会根据TCP头部中的序列号等信息验证数据包的有效性,并将数据包缓存起来,等待应用层读取。
应用层通过Socket监听特定端口,当读取数据时,操作系统内核会根据TCP头部中的端口号,将数据包发送给相应的应用程序进行处理。这样应用程序就可以读取并处理网络包了。
在应用层中,我们需要解析HTTP头和正文,这是由应用层来处理的。应用框架(如Tomcat等)通常会帮助我们解析和处理数据包(粘包问题等),因此我们不需要过多考虑网络层面的细节。通过解析,应用层能够得知客户端的请求,例如购买商品或请求网页。一旦应用层处理完HTTP请求,结果会被封装为HTTP网络包,通过Socket接口发送给内核。
接下来,内核会对数据包进行多层封装,从物理网口发送出去,经过网络2的交换机和Linux路由器,最终到达网络1。在网络1上,数据包经过网络1的交换机,再次经过Linux服务器A的层层解封装,然后通过Socket接口根据客户端的随机端口号发送给客户端应用程序,即浏览器。这样,浏览器就能够显示一个绚丽多彩的页面了。
需要注意的是,这个示例比较简单,所以返回请求的路径与发送路径相同。但在实际情况中,返回请求的路径不一定是原路返回,而是再次经过上述的网络处理逻辑。这是因为网络中的路由器会根据路由表选择最佳路径,以确保数据包能够快速、高效地到达目标设备。
即使在这个相对简单的网络环境中,发送数据包的过程也是非常复杂的。
总结
发送数据包是一个复杂的过程,涉及到多个层次的封装和解封装。不同层次的协议和设备在这个过程中扮演着不同的角色,确保数据包能够快速、高效地到达目标设备。在发送数据包的过程中,数据包会经过多个网络设备和路由器,每一步都需要进行相关的处理和解析。发送数据包的过程需要考虑到各个层次的处理和协议的兼容性,以确保数据包能够正确地到达目标设备,并被相应的应用程序处理。这个过程中涉及到的细节非常复杂,需要各个层次的协议和设备之间的配合和交互,才能实现数据的传输和交换。
我是努力的小雨,一名 Java 服务端码农,潜心研究着 AI 技术的奥秘。我热爱技术交流与分享,对开源社区充满热情。同时也是一位腾讯云创作之星、阿里云专家博主、华为云云享专家、掘金优秀作者。
💡 我将不吝分享我在技术道路上的个人探索与经验,希望能为你的学习与成长带来一些启发与帮助。
🌟 欢迎关注努力的小雨!🌟