网络协议分层的知识几乎是所有技术公司面试的题目。大多数求职者在面试前死记硬背所有的分层,面试的时候对答如流,面试后全还给面试者了。面试者也很满意,因为他也知道,在实际的项目中,大家都不会用到这些鬼东西了。并且他也不一定比面试者背诵的内容懂得更多。
我并不是对面试者“死记硬背”网络协议分层概念吹毛求疵,这多多少少是大学计算机教育的悲哀。 业界本来“计算机科学”的素养就不够,再没有“软件工程”的基本能力,只能沦为没有创造力的外包工人。对网络协议分层知识的考察如果不涉及各个层次涉及的设备,就只能退化为记忆力的竞赛,更没有体现“网络”本身的味道和精神。
何为协议?仔细理解理解一下PDU,帧,分组,数据段和消息的区别,然后扩展一些网络两端解包封包的内容,明白各协议是如何在网络的两端对各层添加/去除包头/包尾的,更要深刻理解数据是如何从一端的协议栈逐层下沉,在对端的协议栈逐层上升。
如何理解分层?从冲突域和广播域开始,明白集线器,交换器,路由器,网关的区别,扩展一些以太网共享介质,CSMA/CD机制和路由的知识,对比联想一下村口的广播,烽火台,邮递员和网络实现的关系。
其实,网络通信的本质有两点。第一,消息能够送达;第二,消息能够被解析。第一点有广播和路由来保证,第二点有协议簇来保证。
传统共享式以太网的典型代表是总线型以太网。在这种类型的以太网中,通信信道只有一个,采用介质共享(介质争用)的访问方法(CSMA/CD介质访问方法)。每个站点在发送数据之前首先要侦听网络是否空闲,如果空闲就发送数据。否则,继续侦听直到网络空闲。如果两个站点同时检测到介质空闲并同时发送出一帧数据,则会导致数据帧的冲突,双方的数据帧均被破坏。这时,两个站点将采用"二进制指数退避"的方法各自等待一段随机的时间再侦听、发送。这就相当于大家在一个房间内同时高声说话(说话即广播),当谁也听不清楚了,就按照算法询问一下,有人说没?没人说了再说。通俗的说,基于CSMA/CD介质访问方法推论,只要基于广播的方式发送信息而会发生冲突的范围,都是冲突域。中继器和集线器都只是对网络通信距离的延展,处于同一个冲突域和广播域之中。也就是说,中继器和集线器既不能隔离冲突域,也不能隔离广播域。
如果面试者被问及网络协议分层能够从冲突域,广播域出发,再引申出四层功能来,那么就可以直接录用了。
网桥可以隔离冲突域,但不能隔离广播域。网桥又称为桥接器。和中继器类似,传统的网桥只有两个端口,用于连接不同的网段。和中继器不同的是,网桥具有一定的"智能"性,可以"学习"网络上主机的地址,同时具有信号过滤的功能。网桥可以识别桥接网络的数据流,主机对主机的通信则不会转发到另一个网段,而广播类型的数据包则会被网桥转发。这里要把CSMA/CD介质访问方法的广播原理和网络通信的广播类型(二层广播即单播和三层广播)区别看待。
交换机被称为交换式集线器。它的出现是为了解决连接在集线器上的所有主机共享可用带宽的缺陷。交换机是通过为需要通信的两台主机直接建立专用的通信信道来增加可用带宽的。从这个角度上来讲,交换机相当于多端口网桥。那么交换机的冲突域就是交换机的一个接口,接口和接口之间则不是一个冲突域。在一个接口上如果连接了集线器,集线器上所有的主机都在一个冲突域中。但是,交换机同样没有过滤广播通信的功能。如果交换机收到一个广播数据包后,它会向其所有的端口转发此广播数据包。因此,交换机和其所有接口所连接的主机共同构成了一个广播域。我们将使用交换机作为互连设备的局域网称为交换式局域网。
到目前为止,在一个广播域内,消息能够送达是靠广播(类比基本靠吼,这就是链路层,没有超出一箭之远),网络地址主要是MAC地址(网卡出厂全球唯一地址,类比身份信息),协议解析只用到以太网协议:Ethernet和IEEE 802.3等(类比中文,英文等)。当然还有其他的一堆协议,不一一列举。
路由器工作在网络层,可以识别网络层的地址——IP地址,有能力过滤第三层的广播消息。实际上,除非做特殊配置,否则路由器从不转发广播类型的数据包。因此,路由器的每个端口所连接的网络都独自构成一个广播域。
到这里,突然觉得网络层也清晰起来。
网络层是可以识别IP地址的层,也就是通过路由器寻找IP地址,就可以定位一个网络(类比邮递员)。由于地址中网络层包了主机的链路层地址,在定位到的网络中广播(吼一声)就可以找到目标主机了。但是路由器只关心网络地址,定位目标主机的任务交给目的网络的交换机即可。所以用到的协议是IP协议,ARP协议等(也有管理功能的ICMP)。由此,我们可以总结,互联网上存在大量的主机,而这些主机又分别属于不同的大量网络中,路由的重要作用就是定位到目标主机所在的网络,从IP地址的分类和IP地址分为网络地址和主机地址两部分,应该可以明白网络层的含义(而不用刻意去记)。
为了提供传输控制,引入了两种传输类型迥异的传输协议TCP和IP。复杂的传输控制方法和对比,这里不展开讨论。重点是,从上面的讨论,已经可以定位网络中的一台主机,而一台主机上可以运行很多应用程序(绑定监听端口的应用程序又称为服务,即响应外部请求,向外提供服务),如何知道网络上发过来消息应该有那一个应用程序处理呢?端口号的作用就是用来区分应用程序(我们知道,一个端口是不能被不同的应用程序重复绑定的),但端口号只会在应用层处理,在传输层是透明传输,不做处理。研究传输层,可以通过对比的分析TCP和IP的差异深入理解为什么引入传输层(在不可靠的网络层和应用层之间,提供一个中间层)。
应用层只是调用socket接口,负责处理特定的应用程序细节。在socket接口中,需要明确的指定TCP还是UDP。其实到了应用层,开发者可以根据需要增加各种不同的首部,定义新的协议。在应用层需要强调的是,Linux/UNIX的哲学是一切皆文件,外部设备也被视为文件,而网络数据的收发和读写打破了这一切。应用层接口并没有与Linux/UNIX文件接口保持一致,而是设计了一套称为套接字socket的特殊接口。《深入Linux内核架构》中给出了一个理由:网络中的所有层次使用了许多不同的通信协议,为建立连接需要指定许多选项,而且无法在打开设备文件时完成这些任务。20世纪80年代的BSD UNIX程序员也曾经为此头痛,套接字的接口就是最终采用的解决方案,而今已成为事实的工业标准。
1988年David D. Clark在其《互联网架构的设计哲学》中总结当初设计互联网的最高层次目标是:在一个基于分组交换的通讯设备中,大量的不同的网络通过使用一种称为网关的包通讯处理机连接在一起,其中网络中节点,包括路由器,网关的实现都采用了一种存储转发包的思想。这个目标里面提到了几个关键词:分组交换,网关,分组。这些关键词体现了网络设计的一些重大决策,比如,采用分组交换是存储转发和多路复用的基础,引入网关的实现多个不同网络互连,并且网关不保留实质性连接状态信息和包的序列信息(网关按包独立转发),分组的设计是网络协议的基础。
文章还讨论了一个很有挑战性的问题:架构与性能之间的关系。 互联网结构的设计者强烈地认为,仅仅重视逻辑正确性而忽视性能是一个重大错误。 但是,他们在提升受到架构限制的任何方面的性能的尝试中遇到了很大困难。 这些困难产生的原因有二,首先这个架构的目标不是保证性能,而是提供多样性,其次(也许更基本),因为看来不存在正式的工具来描述性能。这也提出了关键性的另一个问题,就是在体系结构中如何规范的描述结构性能问题,以期能切实指导实践者,单纯的指明“这个网络能吞吐多少数据”并不能解决根本性的问题,也不是体系结构需要进行描述的。
一个系统是与其所运行的环境高度配合的,商业利益清单可以很容易的对目标进行问责。从批评者的语言里思考一下,或许可以得到一些灵感。
2006年Geoffrey G. Xie在论文《互联网架构:回顾和展望》中总结了互联网架构设计的三大原则。第一点是牺牲效率获得简单性,其后果是网路对底层硬件和上层应用需求都不做任何假设,衍生了复杂的QoS,传输控制和流量工程等。第二点是报文服务,目前也被称为IP细腰,逻辑上看,这个细腰构成网络上数据流动的协议水位线。其缺点是网络设备不感知数据内容。第三点是端到端论断,和IP细腰一起,让整个网络以主机为中心,而不是以数据为中心。ACM通讯上发布文章《网络命名内容》,提出了对内容进行编址,用内容细腰替代IP细腰的一家之言。
【本文是51CTO专栏作者石头的原创文章,转载请通过作者微信公众号补天遗石(butianys)获取授权】