Post

关于网络协议设计的探讨以及背后本质的思考

今天面试了家公司,面试官向我提出个问题,引发了我的思考。作为后台开发人员,我总是拘泥于掌握网络协议的工作过程和使用流程,以为了解网络协议的工作流程就能对保证正确的使用协议栈。但是面试官向我强调,很多时候互联网的新技术、新概念的出现,其实其本质的东西和一些古老的技术是相通的。我需要去理解这些技术背后的本质,就像是协议栈中的tcp和udp,需要知道其为什么存在面向连接和不面向连接的原因,存在的来由是什么,是从怎样的设计理念而来的。

互联网的技术组件越来越多、越来越新,但是根本上的互联网的设计原则是不变的,如果违背设计原则去创造新的技术,没有得到历史的考验,是经不住业务的考验的。因此要理解互联网的设计原则。

首先我们第一个接触到的设计原则:分组交换。互联网的设计原理是分组交换的无连接网络,分组交换指的是,需要被传输的数据被分割成大小相等的小片,每一个小片都携带源地址和目标地址,这些小片独立通过网络。这些小片的名字叫packet。为什么要这样设计呢,本质上是动态分配传输资源,不会出现网络端口被占用的情况。而避免这样情况的发生的原因,就是起点和重点的数据传输存在多条传输路径,数据传输的过程中,哪怕有一条被占用,也可以选择其他的路径。但是为了避免传输延迟,我们就需要选择最小的传输路径,这就是网络层路由协议的由来,热土豆、BGP、OSPF、RIP等现代路由协议就是为了这个需求实现的。分组交换的过程是无连接的,对于每个传输中的数据包,中间的计算机只负责储存转发,不会对可靠性和有序性进行保证。

还有可问题,就是这些小的packet的分包和重组是在哪里完成的呢?答案是发送端和接收端,这就是互联网的另一个设计理念:端到端。发送端和接收端的计算机天然适合这种复杂的工作。

从最底层的链路层来看,链路层的设计原则讲究分组交换、尽力而为,即链路层的作用是保证数据尽可能传输到目标主机,而不保证其可靠性和有序性。所以我们看到链路层中帧的设计是mac地址+其他的东西,通过arp和mac地址去找到目标主机的mac地址,并向它发送过去。这就是链路层做的事。

网络层的设计是不是也很像,也是分组交换、尽力而为,网络数据包的头部也是ip地址,通过内部路由表找到下一跳要前往的ip地址,并发送过去。也是无连接的。

任何互联网的技术的设计都是需求驱动的,是为了解决需求产生的。传输层的底层采用无连接的设计思想,代表其数据传输的可靠性和有序性是无法被保证的,但是我们有需要为上层服务提供可靠的和有序的传输保障,保证数据不会丢失以及有序到达。这个需求就作为tcp协议的设计理念来。根据端到端的设计理念,这个需求需要我们在发送端和接收端完成。如何在传输层保证数据的有序性和可靠性呢?首先是可靠性,tcp会通过ack确认发送的数据包被接收端接收到,如果没有被接收到,会采用重传机制来保证;然后是有序性,tcp会为每一个数据包分配连续的seq序列号,根据序列号对接收到的数据进行排序。但是为了保证这一过程的连贯性,tcp的工作会维护一个状态,这个状态会占用双方,也就是ip+端口,tcp需要保证一个唯一的四元组来保证发送端和接收端处于连接状态,其他的连接请求会被拒绝。这种占用端口的行为就是建立连接的行为,很像我们早期的打电话,一方被占用到了,就无法给他打电话了。面向连接是为了保证有序性和可靠性的工作不被干扰而产生的。

然后就是udp,如果没有有序性和可靠性的需求,而是对低延迟、高效传输的需求,那么udp就是一个合适的选择。udp的设计理念沿用了底层网络层和链路层,是分组交换和尽力而为,它不会对数据包的传输进行额外的控制和确认,发送端只需要将数据包发送出去,而接收端也不需要对数据包的接收进行确认。这种设计使得udp在传输层能够提供更低的延迟和更高的传输效率,适用于一些对实时性要求较高的场景,比如视频会议、在线游戏等。

到这里,大家可能就对面向连接和无连接的设计理念有了深入的了解。这让我意识到,许多技术的产生具备历史的必然性,当我们在学习新技术时,除了关注其实现的优雅,更要关注其发展的前身和解决的需求。

This post is licensed under CC BY 4.0 by the author.