我们每天都在使用的互联网,你是否好奇,它是如何实现的?全世界接入互联网的终端设备有几十亿台,为什么你的电脑能从中准确的找到小伙伴的电脑,然后相互进行通信?如果让你从零开始设计能使全球的终端设备互联互通的计算机网络,你会怎么实现?
什么是互联网
我们先来看一张图
互联网的组成
名词解释:
- Mobile Network 移动网络
- National or Global ISP 国家或全球 ISP
- ISP Internet Service Provider 互联网服务供应商
- Home Network 家庭网络
- Local or Regional ISP 本地或区域 ISP
- Enterprise Network 公司网络
- Host 主机
- end system 端系统
- Server 服务器
- Mobile 移动设备
- Router 路由器
- Link-Layer switch 链路层交换机
- Modem 调制解调器
- Base station 基站
- Smart phone 智能手机
- Cell phone tower 蜂窝电话塔
互联网是指由若干个电子计算机网络相互连接而成的更大的网络,即网络的网络。
互联网的结构
概述
- 互联网分为多层,每一层都有自己的功能。上层与下层之间的关系就像建筑物一样,上层需要来自下层的支持。
- 为了统一某一层的功能,大家在具体实现这一层的时候就需要遵守共同的规则,或者叫『协议』(protocol)。
- 越下面的层,越靠近硬件;越上面的层,越靠近用户。
网络分层
Physical Layer
搭建一个网络,第一件事要干什么?
当然是先把电脑们连接起来,可以用光缆、电缆、双绞线、无线电波等方式。
连接电脑
光缆
电缆
双绞线
无线电波
这就叫做『实体层』,它是把电脑连接起来的物理手段,主要作用是负责传送 0 和 1 的电信号。
Link Layer
有了『实体层』,现在我们已经能互相传递 0 和 1 了。假设:
你传 0101010101010010101010101010010101010101001101010100110100100101001 给我,
我回 1001000010101010101000010100011111110001010101010010101010101001010 给你。
但是,这一连串的 0 和 1 该怎么解读呢,是不是看的一脸懵逼?
这是因为我们还缺一个将 0 和 1 分组的方式。
Frame
早期的时候,每家公司都有自己的电信号分组方式。逐渐地,一种叫做『以太网』(Ethernet)的协议,占据了主导地位。以太网规定,一组电信号构成的一个数据包,叫做『帧』(Frame)。每一帧分成两个部分:Head 和 Data。
Frame
IEEE 802.3
以太网帧结构
名词解释:
- Octet 八位元组 (像 11110000 就是一个 octet)
- Preamble 序文 (由 7 个 10101010 和 1 个 10101011 组成)
- SFD Start Frame Delimiter 帧首定界符 (1 个 octet 10101011)
- Destination MAC 目的 MAC 地址
- MAC Media Access Control Address 以太网地址
- Source MAC 源 MAC 地址
- 802.1Q Header 可选字段
- EtherType 以太类型
- Payload 有效载荷 (42-1500 个 octet)
- CRC Cyclic Redundancy Check 循环冗余校验
- FCS Frame Check Sequence 帧检查序列
- Inter Frame Gap 帧间间隔
MAC
1990 年代的以太网网卡或叫 NIC(Network Interface Card,以太网适配器)。这张卡可以支持基于同轴电缆的 10BASE2 (BNC 连接器,左)和基于双绞线的 10BASE-T(RJ-45,右)。
以太网网卡
每块网卡出厂的时候,都有一个全世界独一无二的 MAC 地址,长度是 48 个二进制位,通常用 12 个十六进制数表示。前 6 位由 IEEE 决定如何分配,后 6 位由实际生产该网络设备的厂商自行指定。
MAC 地址
mac 上可以用 ifconfig 命令查看 MAC 地址
MAC 地址现在已经定义好了。
那么下一个问题来了:一块网卡怎么会知道另一块网卡的 MAC 地址?其实,在每台安装有 TCP/IP 协议的电脑或路由器里都有一个 ARP 缓存表(IPv6 中使用 NDP 协议代替了 ARP 协议),表里的 IP 地址与 MAC 地址是一一对应的。如下表所示:
主机名称 | IP 地址 | MAC 地址 |
---|---|---|
A | 192.168.38.10 | 00-AA-00-62-D2-02 |
B | 192.168.38.11 | 00-BB-00-62-C2-02 |
C | 192.168.38.12 | 00-CC-00-62-C2-02 |
… | … | … |
以主机 A(192.168.38.10)向主机 B(192.168.38.11)发送数据为例。
- 当发送数据时,主机 A 会在自己的 ARP 缓存表中寻找是否有目标 IP 地址。
- 如果有,直接把目标 MAC 地址写入帧里面发送就行。
- 如果没有,主机 A 就会在网络上发送一个广播(ARP request)。
目标 MAC 地址是『FF.FF.FF.FF.FF.FF』,这表示向同一网段内的所有主机发出这样的询问:『192.168.38.11 的 MAC 地址是什么?』
网络上其他主机并不响应 ARP 询问,只有目标主机 B 接收到这个帧时,才向主机 A 做出这样的回应(ARP response):『192.168.38.11 的 MAC 地址是 00-BB-00-62-C2-02』。
这样,主机 A 就知道主机 B 的 MAC 地址,它就可以向主机 B 发送信息。同时它还更新自己的 ARP 缓存表,下次再向主机 B 发送信息时,直接从 ARP 缓存表里查找就可。ARP 缓存表采用老化机制,在一段时间内如果表中的某一行没有使用,就会被删除,这样可以大大减少 ARP 缓存表的长度,加快查询速度。
以上就是 ARP 协议原理的简单描述。
mac 上可以用 arp -a 命令查看 ARP 缓存表
这就是『链接层』的功能,它在『实体层』的上方。确定了 0 和 1 的分组方式,它的数据包被称为 Frame。
Network Layer
有了以太网协议,我们依靠 MAC 地址来发送数据。理论上,全世界的电脑互联互通已经可以实现了。还有什么不足吗?有的。
这样做有一个重大的缺陷:如果两台计算机不在同一个子网络,广播是传不过去的!
那为什么不设计一个超级大的子网络呢?因为以太网采用广播方式查询未知计算机的 MAC 地址,所有成员人手一帧。就算可以设计一个超级子网,那么互联网上每一台计算机都收到所有帧,这将会是一个灾难。
因此,必须找到一种方法,能够区分哪些 MAC 地址属于同一个子网络。如果是同一个子网络,就采用广播方式发送,否则就采用『路由』方式发送(这里的『路由』指的是如何向不同的子网络分发数据包)。遗憾的是,MAC 地址本身无法做到这一点——它只与厂商有关,与所处网络无关。
这就导致了『网络层』的诞生。它的作用是引进一套新的地址,使得我们能够区分不同的计算机是否属于同一个子网络。这套地址就叫做『网络地址』,简称『网址』。
IP
规定网络地址的协议,叫做 IP 协议。它所定义的地址,就被称为 IP 地址。目前,广泛采用的是 IP 协议第四版(即 IPv4)。这个版本规定,网络地址由 32 个二进制位组成。
IP 地址
习惯上,我们用分成四段的十进制数表示 IP 地址,从 0.0.0.0 一直到 255.255.255.255(存在一些特殊的 IP 地址)。互联网上的每一台计算机,都会分配到一个 IP 地址。这个地址分成两个部分,前一部分代表网络,后一部分代表主机。比如,IP 地址 172.16.254.1,这是一个 32 位的地址,假定它的网络部分是前 24 位(172.16.254),那么主机部分就是后 8 位(上图的 IP 地址的主机就是最后的那个 1)。
Subnet Mask
那么问题来了:怎样才能从 IP 地址,判断两台计算机是否属于同一个子网络呢?这就要用到另一个参数『子网掩码』(subnet mask)。
所谓『子网掩码』,就是表示子网络的一个参数。它在形式上和 IP 地址类似。但它有个显著的特点:它的网络部分全部为 1,主机部分全部为 0!
比如,IP 地址 172.16.254.1,如果已知网络部分是前 24 位,主机部分是后 8 位,那么『子网掩码』就是 11111111.11111111.11111111.00000000,写成十进制就是 255.255.255.0。知道了『子网掩码』,我们就能判断,任意两个 IP 地址是否处在同一个子网络。方法是将两个 IP 地址与『子网掩码』分别按位进行 AND 运算(两个数都为 1,则运算结果为 1,否则为 0),然后比较结果是否相同,如果是的话,就表明它们在同一个子网络中,否则就不是。
- Q
- 已知 IP 地址 172.16.192.1 和 172.16.254.233 的子网掩码都是 255.255.192.0,请问它们是否在同一个子网络?
- A
- 将两者分别与子网掩码进行 AND 运算,结果都是 172.16.192.0,因此它们在同一个子网络中。
Datagram
IP 数据包也分为 Head 和 Data 两个部分。Head 部分主要包括协议版本、数据包长度、IP 地址等信息,Data 部分则是 IP 数据包的具体内容。
IP 数据包中一定包含了 IP 地址。但是前面说过,以太网数据包的 Head 里面只包含 MAC 地址,并没有 IP 地址的栏位。那么是否需要修改以太网数据包的 Head 定义,再添加一个栏位来存放 IP 地址信息呢?
回答是不需要,我们可以把 IP 数据包直接放进以太网数据包的 Data 部分,因此完全不用修改以太网数据包的定义。这就是互联网分层结构的好处:上层的变动完全不涉及下层的结构。它放进以太网数据包后,以太网数据包就变成了下面这样。
Datagram
IP 数据包的 Head 部分的长度为 20 到 60 字节,整个数据包的总长度最大为 65535 字节。因此,理论上,一个 IP 数据包(Datagram) 的 Data 部分,最长为 65515 字节。前面说过,以太网数据包(Frame)的 Payload 部分,最长只有 1500 字节。因此,如果一个 IP 数据包超过了 1500 字节,它就需要分割成几个以太网数据包,分开发送了。
『网络层』在『链接层』的上层。它的作用主要有两个,一个是为每一台计算机分配一个网络地址;另一个是确定哪些网络地址在同一个子网络。它的数据包被称为 Datagram。
Transport Layer
有了 MAC 地址和 IP 地址的情况下,我们已经可以在互联网上任意两台主机上建立通信。为什么还要传输层呢?
这是因为在同一台主机上将会有许多程序都需要用到网络。
比如,你一边浏览网页,一边与朋友在线聊天。当一个数据包从互联网上发来的时候,计算机怎么知道,它是表示网页的内容,还是表示在线聊天的内容?也就是说,我们还需要一个参数, 来表示这个数据包到底供哪个进程使用。
Port
这个参数就叫做『端口』(port),由 16 位二进制表示(0-65535),它其实是每一个使用网卡的程序的编号。每个数据包都发到主机的特定端口,所以不同的程序就能取到自己所需要的数据。
0-1023 号端口被称为 知名端口(well-known port)。这些知名端口号由 IANA 分配。用户只能选用 1024-65535 之间的一个端口号。不管是浏览网页还是在线聊天,应用程序随机选用一个端口,然后与服务器的相应端口联系。
UDP
现在,我们必须在数据包中加入端口信息,这就需要新的协议。最简单的实现叫做 UDP(User Datagram Protocol)协议,它的格式几乎就是在数据前面加上端口号。
UDP 数据包,也是由 Head 和 Data 两部分组成。Head 部分定义了发出端口和接收端口,Data 部分就是具体的内容。
整个 UDP 数据包放入 IP 数据包的 Data 部分,而前面说过,IP 数据包又是放在以太网数据包之中的,所以整个以太网数据包现在变成了下面这样:
Segment
UDP 数据包最长可为多少字节?
UDP 数据包非常简单,Head 部分一共只有 8 个字节,总长度不超过 65515 字节,正好放进一个 IP 数据包的 Data 部分。
TCP
在 TCP/IP 模型中,UDP 为网络层以上和应用层以下提供了一个简单的接口。UDP 只提供数据的不可靠传递,它一旦把应用程序包装给网络层的数据发送出去,就不保留数据备份(所以 UDP 有时候也被认为是不可靠的数据报协议)。UDP 在 IP 数据报的头部仅仅加入了复用和数据校验(字段)。
为了解决这个问题,提高网络可靠性,TCP 协议就诞生了。这个协议非常复杂,但可以近似认为,它就是有确认机制的 UDP 协议,每发出一个数据包都要求确认。如果有一个数据包遗失,就收不到确认,发出方就知道有必要重发这个数据包了。TCP 数据包和 UDP 数据包一样,都是内嵌在 IP 数据包的 Data 部分。TCP 数据包没有长度限制,理论上可以无限长,但是为了
保证网络的效率,通常 TCP 数据包的长度不会超过 IP 数据包的长度,以确保单个 TCP 数据包不必再分割。
Segment
传输层的数据包,被称为 Segment。
『传输层』的功能,就是建立『端口到端口』的通信。相比之下,『网络层』的功能是建立『主机到主机』的通信。只要确定主机和端口,我们就能实现程序之间的交流。因此,Unix 系统就把 主机 + 端口,叫做『套接字』(socket)。有了它,我们就可以开发网络应用程序了。
Application Layer
应用程序成千上万,而『应用层』的作用,就是规定应用程序的数据格式。常见的应用层协议如下:
- HTTP(HyperText Transfer Protocol)
- 缺省 TCP 80 端口,用于浏览器浏览网页。但网页内容为明文,易被篡改、易被劫持、网页内容易泄露。
- HTTPS(HyperText Transfer Protocol Secure)
- HTTPS 中的 S 代表 Security,缺省工作于 TCP 443 端口,原理是在 HTTP 与 TCP 层之间多了一个安全加密的夹层,称之为 SSL(Secure Socket Layer),用于加密基于 HTTP 的网页内容。不易篡改、不易劫持、网页内容保密,目前广泛用于网上银行、网上支付等业务。但有安全漏洞,容易受中间人攻击,所以需要引入 CA 证书体系进行身份认证。
- SMTP(Simple Mail Transfer Protocol)
- 用于发送邮件的基于 TCP 的应用层协议。
- POP3(Post Office Protocol - Version 3)
- 用于接受邮件的基于 TCP 的应用层协议。
- DNS(Domain Name System)
- 用于将域名解析成 IP 地址的基于 UDP/TCP 的应用层协议。
- DHCP(Dynamic Host Configuration Protocol)
- 用于主机动态获取 IP 地址、缺省网关、DNS 服务器等参数的基于 UDP 的应用层协议。
- NFS(Network File System))
- 用于 Unix/Linux 文件共享,基于 UDP/TCP 的应用层协议。
- NTP(Network Time Protocol)
- 用于时钟同步的基于 UDP 的应用层协议。
- RTP(Real Time Protocol)
- 用于 IP 多媒体电话的语音、文字、视频等流体的传输,基于 UDP 的应用层协议。
Message
『应用层』是最高的一层,直接面对用户。它的数据包被称为 Message。
总结
我们最后来看一张图
应用程序之间的消息传输过程
网络应用程序之间需要交换的 Message 由源终端的 Application Layer 开始,层层包装,最后形成一个个 Frame。Frame 经由若干个 Link-layer switch 和 Router 的传输,送达到目的终端。再由目的终端的 Physical Layer 开始,层层解析,最终把 Message 交付给目标应用程序。至此,网络应用程序之间就完成了一次 Message 的传输。
为什么要这样设计
- 为什么互联网要采用分层设计?
- 网络层的作用是什么?
- 如果重头开始设计互联网,你还会分这么多层吗?