(0)我想学学计算机网络

46 阅读7分钟

前言

最近在学习kubernetes,过程中比较头疼的一个问题就是容器网络。从宿主机与容器的通信、到同一宿主机上,容器与容器之间的通信、再到更复杂的跨宿主机的容器与容器的通信,都有其背后的实现原理。我在学习过程中,看到了docker0网桥,觉得熟悉又陌生,网桥这个词听到的太多了,但它到底干什么用的? 大部分网络方面的知识点给我的感觉都是这样,似乎都懂,但一细想就又挺懵的,这次索性好好整理下。

我的思路是从go语言应用出发,通过抓包去学习机器与机器之间如何进行网络通信的。

关于机器与机器之间是如何网络通信的。这个问题可以拆分成几个部分。

第一部分:

首先需要知道它们之间通信的是个什么东西,当然是网络包,那这个网络包是什么样子的?

[网络包]  应用层的消息,到了各层形式会有一定的转变,比如到达传输层变成了Segment,到达网络层变成了Packet,到达数据链路层变成了Frame,最后到了物理层就是比特流了。不过我觉得这种转变不影响理解核心的网络原理学习,所以我统一称为网络包了。

网络包的结构与网络分层有非常强的对应关系,所以需要了解网络分层的原理,该系列的第一篇分享的内容就是:

  • go http发起请求聊聊网络分层

为了直观的看到网络包的样子,文章会借助Wireshark抓包,通过分析各层的关键网络协议,理解各层的作用。

第二部分:

知道了机器间通信的内容,还有个关键问题:机器A怎么知道机器B在哪?

机器A能找打机器B的前提是,两台机器得是连着网的。网络中机器非常多的时候,肯定无法做到任意两台机器时间都是网线直连,而是会通过很多交换机。所以就需要知道众多机器是怎么连起来的。在此基础上,才能根据不同的连网情况分析出机器A是如何找到机器B的。该系列的第二篇分享内容就是:

  • 网络世界的机器是如何连接起来的

第三部分:

做为开发者,使用的最多的应用层协议就是HTTP协议,众所周知,HTTP是基于TCP的,为了更好的了解HTTP协议的特点,首先需要对TCP有一个清晰的认知。该系列的第三篇分享内容就是:

  • 抓包感受"看得见"的TCP

第四部分:

由于我自己是一个go程序员,我会从go http的运用分析go的并发网络模型,该系列的第四篇分享内容就是:

  • go的并发网络模型

第五部分:

在了解了底层网络的基本运作原理后,最后会回机器之间通信最常用到的应用层协议上来,挑选了最常用的两个应用层协议:

  • HTTP没我想的那么简单
  • 微服务世界至关重要的RPC

关于IP地址

在整个系列之前,先聊聊IP地址。IP地址没有看起来的那么简单。

首先,连网成功的机器,一定会有一个IP地址。准确的说,IP地址不是机器的,是机器上面某一张网卡的。

在公司的时候,自己的IP地址经常和隔壁工位同事的IP地址非常像,比如我的是192.168.1.17,他是192.168.1.20。是因为我们的连网情况是属于同一个网段。

  • 💡:网段,官方的概念:一般指一个计算机网络中使用同一物理层设备(传输介质,中继器,集线器等)能够直接通讯的那一部分。
  • 是不是看了和没看一样?好多网络概念的官方解释都如此。我建议学习网络不要在概念定义上钻牛角尖,重点是能理解网络世界运行的基本原理。
  • 网段用个人的话来说,就是仅用二层交换机可达的机器组成的一个网络。二层交换机是什么?在后面的网络世界的机器是如何连接起来的部分会有解释。

那么IP地址实际上可以拆成两部分:192.168.1这个不变的表示是哪个网段,17、20是各自的主机号,组在一起就是同一网段的不同IP地址。

这种方式就是CIDR,无类型域间选路。无类型是相对于将IP地址区分成A、B、C、D、E五类的方式,由于分类方式已经不太适用于现在的网络使用情况了,现在无类型才是主流。

一个完整的无类型IP地址应该是:192.168.1.17/24,表示这个IP的前24位是网络号(网段),后8位是主机号。

  • 计算机用二进制表示IP地址,每个 . 隔开的部分是8位二进制数,总共是32位,每一段换成十进制就是在[0,255]区间内。
  • 192.168.1.17的二进制表示就是:11000000.10101000.00000001.00010001

每一个网段还有自己的网关地址,一般是这个网络号的第一个主机号,即:192.168.1.1。这主要用于网段与网段之间的通信,后面会详细描述。

每一个网段都有自己的广播地址,一般是这个网络号的最后一个主机号,即:192.168.1.255。如果向这个地址发送网络包,该网段内的所有机器都可以收到。

那么操作系统是如何根据IP地址,计算其所属的网段呢?

这就需要子网掩码。以192.168.1.17/24为例,它相对应的子网掩码是255.255.255.0(前24位都是1,后8位是0)。如果将192.168.1.17和255.255.255.0做AND运算。

  • 1 AND 0 = 0、1 AND 1 = 1、0 AND 1 = 0、0 AND 0 = 0
  • (11000000 10101000 00000001 00010001)AND (11111111 11111111 11111111 00000000)= 11000000 10101000 00000001 00000000
  • 前24位分别与1做AND运算,都保住了本来的值。后8位分别与0做AND运算,原本值都丢掉了。
  • 11000000 10101000 00000001 00000000 转10进制 192.168.1.0

网络号就计算出来了。

子网掩码为1的位数,可以不是8的整数倍。比如16.158.165.91/22。子网掩码的前22位都是1,11111111 11111111 11111100 00000000,转十进制:255.255.252.0

  • 16.158.165.91的二进制表达是:00010000 10011110 10100101 01011011
  • (00010000 10011110 10100101 01011011)AND (11111111 11111111 11111100 00000000) = 00010000 10011110 10100100 00000000
  • 00010000 10011110 10100100 00000000转十进制 16.158.164.0。
  • 该网段的网关地址是网络号下的第一台主机号地址,即16.158.164.1。
  • 该网段的广播地址就是网络号下的最后一个主机号,即00010000 10011110 10100111 11111111,16.158.167.255