所有最新极客时间课程请加QQ群170701297

第2讲讲网络分层的真实含义是什么?

长时间从事计算机网络相关的工作,我发现,计算机网络有一个显著的特点,就是这是一个不仅需要背诵,而且特别需要将原理烂熟于胸的学科。很多问题看起来懂了,但是就怕往细里问,一问就发现你懂得没有那么透彻。

我们上一节列了之后要讲的网络协议。这些协议本来没什么稀奇,每一本教科书都会讲,并且都要求你背下来。因为考试会考,面试会问。可以这么说,毕业了去找工作还答不出这类题目的,那你的笔试基本上也就挂了。

当你听到什么二层设备、三层设备、四层LB和七层LB中层的时候,是否有点一头雾水,不知道这些所谓的层,对应的各种协议具体要做什么“工作”?

这四个问题你真的懂了吗?

因为教科书或者老师往往会打一个十分不恰当的比喻:为什么网络要分层呀?因为不同的层次之间有不同的沟通方式,这个叫作协议。例如,一家公司也是分“层次”的,分总经理、经理、组长、员工。总经理之间有他们的沟通方式,经理和经理之间也有沟通方式,同理组长和员工。有没有听过类似的比喻?

那么第一个问题来了。请问经理在握手的时候,员工在干什么?很多人听过TCP建立连接的三次握手协议,也会把它当知识点背诵。同理问你,TCP在进行三次握手的时候,IP层和MAC层对应都有什么操作呢?

除了上面这个不恰当的比喻,教科书还会列出每个层次所包含的协议,然后开始逐层地去讲这些协议。但是这些协议之间的关系呢?却很少有教科书会讲。

学习第三层的时候会提到,IP协议里面包含目标地址源地址。第三层里往往还会学习路由协议。路由就像中转站,我们从原始地址A到目标地址D,中间经过两个中转站A->B->C->D,是通过路由转发的。

那么第二个问题来了。A知道自己的下一个中转站是B,那从A发出来的包,应该把B的IP地址放在哪里呢?B知道自己的下一个中转站是C,从B发出来的包,应该把C的IP地址放在哪里呢?如果放在IP协议中的目标地址,那包到了中转站,怎么知道最终的目的地址是D呢?

教科书不会通过场景化的例子,将网络包的生命周期讲出来,所以你就会很困惑,不知道这些协议实际的应用场景是什么。

再问你一个问题。你一定经常听说二层设备、三层设备。二层设备处理的通常是MAC层的东西。那我发送一个HTTP的包,是在第七层工作的,那是不是不需要经过二层设备?或者即便经过了,二层设备也不处理呢?或者换一种问法,二层设备处理的包里,有没有HTTP层的内容呢?

最终,我想问你一个综合的问题。从你的电脑,通过SSH登录到公有云主机里面,都需要经历哪些过程?或者说你打开一个电商网站,都需要经历哪些过程?说得越详细越好。

实际情况可能是,很多人会答不上来。尽管对每一层都很熟悉,但是知识点却串不起来。

上面的这些问题,有的在这一节就会有一个解释,有的则会贯穿我们整个课程。好在后面一节中我会举一个贯穿的例子,将很多层的细节讲过后,你很容易就能把这些知识点串起来。

网络为什么要分层?

这里我们先探讨第一个问题,网络为什么要分层?因为,是个复杂的程序都要分层。

理解计算机网络中的概念,一个很好的角度是,想象网络包就是一段Buffer,或者一块内存,是有格式的。同时,想象自己是一个处理网络包的程序,而且这个程序可以跑在电脑上,可以跑在服务器上,可以跑在交换机上,也可以跑在路由器上。你想象自己有很多的网口,从某个口拿进一个网络包来,用自己的程序处理一下,再从另一个网口发送出去。

当然网络包的格式很复杂,这个程序也很复杂。复杂的程序都要分层,这是程序设计的要求。比如,复杂的电商还会分数据库层、缓存层、Compose层、Controller层和接入层,每一层专注做本层的事情。

程序是如何工作的?

我们可以简单地想象“你”这个程序的工作过程。

当一个网络包从一个网口经过的时候,你看到了,首先先看看要不要请进来,处理一把。有的网口配置了混杂模式,凡是经过的,全部拿进来。

拿进来以后,就要交给一段程序来处理。于是,你调用process_layer2(buffer)。当然,这是一个假的函数。但是你明白其中的意思,知道肯定是有这么个函数的。那这个函数是干什么的呢?从Buffer中,摘掉二层的头,看一看,应该根据头里面的内容做什么操作。

假设你发现这个包的MAC地址和你的相符,那说明就是发给你的,于是需要调用process_layer3(buffer)。这个时候,Buffer里面往往就没有二层的头了,因为已经在上一个函数的处理过程中拿掉了,或者将开始的偏移量移动了一下。在这个函数里面,摘掉三层的头,看看到底是发送给自己的,还是希望自己转发出去的。

如何判断呢?如果IP地址不是自己的,那就应该转发出去;如果IP地址是自己的,那就是发给自己的。根据IP头里面的标示,拿掉三层的头,进行下一层的处理,到底是调用process_tcp(buffer)呢,还是调用process_udp(buffer)呢?

假设这个地址是TCP的,则会调用process_tcp(buffer)。这时候,Buffer里面没有三层的头,就需要查看四层的头,看这是一个发起,还是一个应答,又或者是一个正常的数据包,然后分别由不同的逻辑进行处理。如果是发起或者应答,接下来可能要发送一个回复包;如果是一个正常的数据包,就需要交给上层了。交给谁呢?是不是有process_http(buffer)函数呢?

没有的,如果你是一个网络包处理程序,你不需要有process_http(buffer),而是应该交给应用去处理。交给哪个应用呢?在四层的头里面有端口号,不同的应用监听不同的端口号。如果发现浏览器应用在监听这个端口,那你发给浏览器就行了。至于浏览器怎么处理,和你没有关系。

浏览器自然是解析HTML,显示出页面来。电脑的主人看到页面很开心,就点了鼠标。点击鼠标的动作被浏览器捕获。浏览器知道,又要发起另一个HTTP请求了,于是使用端口号,将请求发给了你。

你应该调用send_tcp(buffer)。不用说,Buffer里面就是HTTP请求的内容。这个函数里面加一个TCP的头,记录下源端口号。浏览器会给你目的端口号,一般为80端口。

然后调用send_layer3(buffer)。Buffer里面已经有了HTTP的头和内容,以及TCP的头。在这个函数里面加一个IP的头,记录下源IP的地址和目标IP的地址。

然后调用send_layer2(buffer)。Buffer里面已经有了HTTP的头和内容、TCP的头,以及IP的头。这个函数里面要加一下MAC的头,记录下源MAC地址,得到的就是本机器的MAC地址和目标的MAC地址。不过,这个还要看当前知道不知道,知道就直接加上;不知道的话,就要通过一定的协议处理过程,找到MAC地址。反正要填一个,不能空着。

万事俱备,只要Buffer里面的内容完整,就可以从网口发出去了,你作为一个程序的任务就算告一段落了。

揭秘层与层之间的关系

知道了这个过程之后,我们再来看一下原来困惑的问题。

首先是分层的比喻。所有不能表示出层层封装含义的比喻,都是不恰当的。总经理握手,不需要员工在吧,总经理之间谈什么,不需要员工参与吧,但是网络世界不是这样的。正确的应该是,总经理之间沟通的时候,经理将总经理放在自己兜里,然后组长把经理放自己兜里,员工把组长放自己兜里,像套娃娃一样。那员工直接沟通,不带上总经理,就不恰当了。

现实生活中,往往是员工说一句,组长补充两句,然后经理补充两句,最后总经理再补充两句。但是在网络世界,应该是总经理说话,经理补充两句,组长补充两句,员工再补充两句。

那TCP在三次握手的时候,IP层和MAC层在做什么呢?当然是TCP发送每一个消息,都会带着IP层和MAC层了。因为,TCP每发送一个消息,IP层和MAC层的所有机制都要运行一遍。而你只看到TCP三次握手了,其实,IP层和MAC层为此也忙活好久了。

这里要记住一点:只要是在网络上跑的包,都是完整的。可以有下层没上层,绝对不可能有上层没下层。

所以,对TCP协议来说,三次握手也好,重试也好,只要想发出去包,就要有IP层和MAC层,不然是发不出去的。

经常有人会问这样一个问题,我都知道那台机器的IP地址了,直接发给他消息呗,要MAC地址干啥?这里的关键就是,没有MAC地址消息是发不出去的。

所以如果一个HTTP协议的包跑在网络上,它一定是完整的。无论这个包经过哪些设备,它都是完整的。

所谓的二层设备、三层设备,都是这些设备上跑的程序不同而已。一个HTTP协议的包经过一个二层设备,二层设备收进去的是整个网络包。这里面HTTP、TCP、 IP、 MAC都有。什么叫二层设备呀,就是只把MAC头摘下来,看看到底是丢弃、转发,还是自己留着。那什么叫三层设备呢?就是把MAC头摘下来之后,再把IP头摘下来,看看到底是丢弃、转发,还是自己留着。

小结

总结一下今天的内容,理解网络协议的工作模式,有两个小窍门:

  • 始终想象自己是一个处理网络包的程序:如何拿到网络包,如何根据规则进行处理,如何发出去;
  • 始终牢记一个原则:只要是在网络上跑的包,都是完整的。可以有下层没上层,绝对不可能有上层没下层。

最后,给你留两个思考题吧。

  1. 如果你也觉得总经理和员工的比喻不恰当,你有更恰当的比喻吗?
  2. 要想学习网络协议,IP这个概念是最最基本的,那你知道如何查看IP地址吗?

欢迎你留言和我讨论。趣谈网络协议,我们下期见!

精选留言

  • 云学
    通信协议就像没有天桥的双子楼,要从A座的24层到达B座24层就得先下楼梯再上楼梯,其他协议也是如此,比如4G
    2018-05-21 08:49
  • 小雨
    很像发快递的过程(http,应用层),你向顺丰下单(第一次请求),顺丰接单(应答),你向手机小伙联系(回应应答),你将消息放进盒子里(开始封装请求,会话层),快递员封装一层盒子贴上快递单带回网店(传输层),到快递点检查是否区域快件(网络层),将快件交给运输车(链路层),各个快递转运中心(物理层),快件到达收件市转运中心(物理层),转运输车(链路层),到达区域分发(网络层),网点派送(传输层),快递员方面签收(会话层),拆开检查(表示层),收到快递(应用层)。
    2018-05-22 00:07
  • 丹丹
    为啥有了ip还需要mac地址,因为没有mac地址网络包发不出去?这个解释还是很模糊看不懂啊
    2018-05-21 08:27
  • qinyingsun
    mac地址局域网寻址,ip地网络寻址,感觉这个作用对理解也很重要
    2018-05-21 08:33
  • 蠢蠢欲动的腹肌
    很多朋友都有疑惑为什么有ip还需要mac地址,其实在老师第一篇文章中已经有了一定的解释,第一篇底下的留言也有不错的说明,个人理解是ip可以保证要发送的包在网络中传输,到达目标服务器所在的局域网的网关,但是到了网关后,ip就没有用了,因为局域网中的ip对应的机器是不确定的,可能今天对应A机器,明天对应B机器。所以在局域网中使用ip寻址是不严谨的,这时就需要mac地址来唯一对应一台机器,这样网络包就可以准确的传输到需要的主机上了。

    另想请教老师,在网关之间传输的时候,下一个网关的ip是如何存储的,这是文章中的问题,但是好像没发现答案,谢谢
    2018-05-23 14:09
    作者回复

    这在后面网关一节有回答

    2018-05-23 15:14

  • 我是谁
    感觉两个问题老师还可以答的更深,不知道是不是篇幅限制:
    1.网络为什么要分层;
    2.有了ip地址,还要mac地址做什么。
    希望老师能够就这两方面给各同学更多的解答
    2018-05-21 11:20
    作者回复

    接下来,会从物理层,二层,三层,一层层讲上去的

    2018-05-21 13:07

  • return
    我觉得就像古代战报传送一样。将军发命令,秘书写。在找人包装盖章,再找人发送,每过一个关卡都要盖公函。到了皇城 一层一层往上。先看是发给那个部门的,去掉一层直接把内容发到上一级。最终到了皇上手里,他无需知道是经过了哪些驿站关卡。只需要知道是哪个将军发的,发的什么。用中文写的还是英文写的就OK了
    2018-05-21 09:24
  • 维尼Bernie
    对于我这样的热门者,觉得这篇不冗余,而且写的很好,原因是这是一篇bigpicture,对后续的学习很有指导意义。
    2018-05-21 09:06
  • chinhu ko
    计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决,计算机整个体系从上到下都是按照严格的层次结构设计的。
    2018-05-26 17:00
    作者回复

    2018-05-26 22:20

  • loveluckystar
    我觉得传输包的过程就是一次快递打包的过程。店家发货,把商品交给快递,快递层层包装,运输给用户。用户拿到以后,并不知道是什么,只知道是给自己的,然后层层拆包装拿到商品
    2018-05-21 08:43
  • MichaelJY
    刚看完,感觉被面试到又gg了……

    我感觉网络层之间的关系可以类比信封发送和接收的过程。邮递员,邮局相当于网络各层。整体下来都是装包和拆包。

    查看ip,我一般用ipconfig/ifconfig……,感觉又有坑点,希望通过整个网络协议的学习,达到知而不惑
    2018-05-21 09:16
  • 陈炽伟
    老师你好,
    我觉得对于 网络为何要分层?这个问题的解释有点过于牵强,虽说复杂的程序都要分层这点没错,但我觉得这只是它的表现,网络每一层协议负责的工作都是不一样的,也就对应了有不同设备来处理。
    比如应用层,一般是由计算机来处理,用于用户可使用的实际程序上;网络层,是网关之间的通讯协议,一般是路由器作处理转发。
    倘若说整个网络只有一层,网络上所有节点都处于同一层级,必然会造成混乱,所以最主要原因还是要明确职责。

    2018-06-02 09:39
    作者回复

    对的,这是架构和设计模式的问题

    2018-06-02 18:11

  • 桐仲康
    就想我们之前写信一样,ip地址是收信人的地址,mac地址对写信人不可见,就是各个邮政局的地址,信件在各个邮政局间传递,mac地址不断变化,最后到达收信人手中。
    2018-05-23 21:02
  • 登高
    实心俄罗斯套娃
    2018-05-21 08:20
  • 约书亚
    这应该算是解答了上一节课的思考题了,就这么简单。翻回头看上节课留言,很多人一两句话解答了,0赞,很多绕了一大圈也没回答到点上的,高票。极客时间应产品经理应该考虑重新定义点赞功能了,对于不不了解这部分知识的人容易被高票误导。甚至在隔壁看到过高票写的内容和老师讲的正相反的情况,结果一堆赞,说明根本也没人细看

    说到process http的例子,确实思考过为什么不能由操作系统或者驱动来实现“部分”(不可能是全部)http协议,让web server开发更简单些

    2018-05-21 09:02
  • Daniel
    可以类比为方法调用过程中的入栈和出栈
    2018-05-23 01:23
  • 哈哈
    为什么网络要分层?,你竟然说,是个复杂的程序就要分层,,,,,,,那么苹果为什么掉到地上,你的解释就是,是个苹果都掉地上咯,,
    2018-07-21 12:16
  • godtrue
    分而治之,这种处理问题的方式是人类解决问题的基本方式之一,尤其针对复杂的问题更是首先会想到使用这种方式来处理。
    比喻,感觉无天桥的双子楼加送快递结合比较合适,有一座无天桥的双子楼一共五层,从上到下的楼层依次命名为应用层、传输层、网络层、链路层、物理层,从A座的应用层发送一个非常珍贵的东西到B层的时候,必须层层打包,然后到B层后必须层层拆包后往上传递。
    2018-08-05 22:18
  • Leo
    因为ip地址是可以随时变化的,而mac地址是机器厂商给每个网卡配置的,是独一无二的,所以需要通过ip地址找到对应的mac地址再传输。并且这个过程所用的方法是ARP协议,即地址解析协议。通过广播的方式找到对应的mac地址。实际过程很复杂,因为ip地址会改变,所以同一个ip对应的mac地址也会变,需要用到其他技术来缓存,看地址是否失效,失效则需要重新使用arp广播查找mac地址
    2018-05-22 19:32
  • Jay
    这个上下层是不是指的内外层,最内层是http包,最外层是Mac地址?
    2018-05-23 21:25
    作者回复

    是的

    2018-05-24 08:13