Linux网络:OS视角下的网络架构
本博客将基于操作系统,讲解计算机网络的设计理念,帮助大家理解操作系统与网络之间的关系。
网络分层模型
网络设计之初,国际标准组织就设计了第一套互联网标准,用于规范互联网,并在全世界推行。这套标准叫做OSI
,即(Open System Interconnection)
开放式系统互连参考模型。
OSI 七层模型
OSI
模型如下:
分层 | 功能 |
---|---|
应用层 | 提供网络服务给应用程序,处理特定应用的网络协议 |
表示层 | 数据表示格式的转换和加密、解密,确保数据格式兼容性 |
会话层 | 管理会话(连接)的建立、维护和终止 |
传输层 | 管理端到端的数据传输,确保数据完整传输 |
网络层 | 负责路径选择和逻辑地址管理,实现跨网络的数据传输 |
数据链路层 | 负责节点到节点之间的数据传输和错误检测 |
物理层 | 处理物理介质上的比特流传输,将数据转化为电信号或光信号 |
OSI
模型通过将网络通信分为七个独立的层,允许每一层专注于特定的功能。这种模块化设计使得开发、测试和维护变得更加容易。每一层可以独立开发、更新或替换,而不影响其他层。
在主流的教材中,把这种模型称为"法律上的标准"
,因为其没有被广泛推行。七层模型有点过于冗余了,实际开发中并不实用。其实七层模型的设计理念是非常优秀的,最后使用的虽然是五层模型,但是在编程时,依然使用七层模型的思想!
TCP/IP 五层模型
TCP/IP
模型如下:
分层 | 功能 |
---|---|
应用层 | 提供应用程序与网络之间的接口,处理特定应用的网络协议 |
传输层 | 负责端到端的数据传输和连接管理,确保数据可靠传输 |
网络层 | 处理跨网络的数据包传输和路由选择,使用IP协议进行逻辑地址管理 |
数据链路层 | 负责节点到节点之间的数据帧传输和错误检测,确保局部网络数据传输可靠 |
物理层 | 处理实际的物理介质上的比特流传输,将数据转化为电信号或光信号 |
相比于OSI
模型,TCP/IP
模型将应用层
,表示层
,会话层
合为了应用层
。这是因为在编程中,这三层的功能都由程序员实现,所以最后干脆都合为应用层了。
对于一个基于TCP
的网络通信过程,用户首先要建立TCP
连接,连接建立成功后就可以收到来自其他主机的数据,此时就要对数据的格式进行处理,比如对数据进行解密,最后将解密的数据进行业务处理。
以上是一个程序员进行网络编程的基本流程,在该流程中,每个步骤都对应一个OSI
的分层:
- 会话层:建立
TCP
连接 - 表示层:对数据的格式进行处理,比如对数据进行解密
- 应用层:将解密的数据进行业务处理
就是因为这三层的功能都由自己编码完成,所以最后这三层就被合并成了应用层
。
协议
在教材中,协议的定义为:
协议是控制两个对等实体进行逻辑通信的规则的集合
协议的目的是为了更加准确高效地在网络传递数据,协议的三要素是:语法
,语义
,同步
。
三要素的含义如下:
语法
:规定通信双方交换信息的结构和格式语义
:规定通信双方交换信息的含义和目的同步
:规定通信双方的时序关系
接下来简单说一个生活中的小案例,帮助理解协议:
在班级中有一群爱打篮球的同学,他们每天最后一节课都要互相问去不去打篮球,决定要不要抢篮球场。但是课堂上是不允许说话的,如果聊天的话会被老师批评。于是同学之间约定,每天最后一节课篮球队长都会敲桌子:
- 如果敲一次桌子:打篮球,下课要去抢篮球场
- 如果敲两次桌子:不打球
- 如果敲三次桌子:踢足球,篮球场已经没有了
队长为了统计有哪些人要参加篮球,于是又约定:等敲完桌子后,谁想参加篮球,就打一个喷嚏,篮球队长就可以更具喷嚏数量来得知篮球的人数。
于是后续每天最后一节课都会发出敲桌子和打喷嚏的声音,因为只有短短几声,老师注意不到,而同学们却都知道了下课要不要打篮球。
这个过程中敲桌子就是一个协议,三要素对应如下:
语法
:通过敲桌子,打喷嚏来传输信息,敲桌子有不同敲击次数语义
:敲桌子和打喷嚏的含义不同,而不同敲击次数的含义也不同同步
:先敲桌子,再打喷嚏,因为喷嚏是敲桌子的响应
你会发现,在规定协议前想去打篮球,要说:"今天下午去篮球场打球,记得抢篮球场",而现在只需要敲一次桌子。由于协议的存在,大幅度压缩了传递信息的成本,并且老师听不懂敲桌子的含义,所以还有一定的加密效果!
在实际的计算机网络中,两个主机之间的距离可能是几十公里,几百公里,甚至半个地球。传递信息的成本非常高,此时协议的重要性就不言而喻了。
你也许见过很多理论课程中的协议格式,比如说TCP
的报头:
但是你多半没有见识过真正的协议,以上图片只是TCP
报头的一个图示,而实际上TCP
报头的本质就是C/C++
中的一个结构体!
在Linux 2.6.10
源码中,TCP
报头的结构体如下:
cpp
struct tcphdr {
__u16 source;
__u16 dest;
__u32 seq;
__u32 ack_seq;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u16 res1:4,
doff:4,
fin:1,
syn:1,
rst:1,
psh:1,
ack:1,
urg:1,
ece:1,
cwr:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u16 doff:4,
res1:4,
cwr:1,
ece:1,
urg:1,
ack:1,
psh:1,
rst:1,
syn:1,
fin:1;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
__u16 window;
__u16 check;
__u16 urg_ptr;
};
比如source
是源地址,dest
是目的地址,中间的fin
,syn
是标志位。此处使用了C语言结构体的位段
语法,不了解的自行学习。
那么为什么TCP
的报头就是C/C++
的结构体?这就和操作系统有关了。
操作系统与网络
我先前在博客[Linux系统:冯诺依曼结构 & OS管理机制]中讲解了操作系统的架构:
这个结构其实和计算机网络有非常大的关系,如下:
其实计算机网络中的每一层都在操作系统中有对应的层次:
网络层次 | 系统层次 | 关系 |
---|---|---|
物理层 | 底层硬件 | 物理层基于操作系统的硬件设备网卡 |
数据链路层 | 驱动程序 | 数据链路层协议在网卡的驱动程序实现 |
网络层 | 操作系统 | IP协议在操作系统内部实现 |
运输层 | 操作系统 | TCP / UDP 协议在操作系统内部实现 |
应用层 | 用户 | 应用层协议由用户自己实现 |
其实网络也属于操作系统源代码的一部分,而主流操作系统是C语言
写的,因此计算机运输层以下的网络协议,都是C语言
结构体完成的。
目前主流的Windows
,Linux
,MacOS
系统的核心也是C/C++
,对应的网络协议栈也就是C/C++
完成。假设现在新出现一个操作系统,是其他语言编写的,那么这个操作系统就无法解析C/C++
的结构体,进而导致无法理解协议的内容,最后无法联网!
世界上所有操作系统,想要联网,就必须遵顼
TCP/IP
协议栈,进而必须使用C/C++
完成网络部分内核
网络相关命令
本博客是Linux
的网络入门文章,接下来再简单了解以下Linux
中基本的网络命令。
ifconfig
不带任何参数运行 ifconfig
会显示所有活动的网络接口的当前配置,如 IP 地址、子网掩码、广播地址、MTU(最大传输单元)等。通过该指令可以了解当前主机的网络接口相关信息。
ifconfig
输出中,显示了两个网络接口的信息:eth0
和 lo
,大多数计算机系统都有多个网络接口。
eth0
是一个有线以太网接口,通常用于连接到外部网络lo
接口是一个特殊的回环接口,通常被称为本地回环接口,数据包发送到这个接口时会被回送到发送者自身
对于eth0
,可以看到:
bash
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
eth0
: 这是网络接口的名称,通常表示第一个以太网接口。flags=4163<UP,BROADCAST,RUNNING,MULTICAST>
: 这些标志表示接口的状态和功能。UP
: 接口已启用,处于活动状态。BROADCAST
: 接口支持广播功能。RUNNING
: 接口正在运行,通常表示接口已连接到网络。MULTICAST
: 接口支持多播功能。
mtu 1500
: MTU(最大传输单元)是接口可以传输的最大数据包大小,单位是字节。对于以太网,默认通常是 1500 字节。
bash
inet 172.29.202.116 netmask 255.255.240.0 broadcast 172.29.207.255
inet 172.29.202.116
: 接口的 IPv4 地址。netmask 255.255.240.0
: 子网掩码,用于确定网络地址和主机地址的部分。broadcast 172.29.207.255
: 广播地址,数据包发送到这个地址时,将会被发送到同一网络中的所有设备。
bash
inet6 fe80::216:3eff:fe10:ec6d prefixlen 64 scopeid 0x20<link>
inet6 fe80::216:3eff:fe10:ec6d
: 这是接口的链路本地 IPv6 地址。fe80::/10
是链路本地地址范围。prefixlen 64
: 表示子网前缀长度为 64 位。scopeid 0x20<link>
: 表示地址的作用域为链路本地(link
),即只在本地链路上有效。
bash
ether 00:16:3e:10:ec:6d txqueuelen 1000 (Ethernet)
ether 00:16:3e:10:ec:6d
: 这是接口的 MAC 地址,用于在以太网层识别设备。txqueuelen 1000
: 这是接口的传输队列长度,通常用于控制传输队列的大小。(Ethernet)
: 表示接口使用的是以太网协议。
ping
ping
是一个用于测试网络连通性和诊断网络问题的命令行工具。它通过向目标主机发送 ICMP回显请求数据包
,并等待接收目标主机返回的回显应答数据包
,来判断目标主机是否可达以及网络的延迟情况。
基本语法:
bash
ping [选项] 目标主机
- 目标主机 :可以是目标主机的 IP 地址、域名(如
www.example.com
)、或者主机名(如localhost
)。
尝试ping www.baidu.com
:
最后所有报文都收到,说明该主机与baidu
之间的连通性是通畅的。
常见选项:
-
-c <次数>
:指定发送的请求次数。默认情况下,ping
会一直发送请求,直到被用户手动中断(通常使用Ctrl+C
)。例如,-c 4
会发送 4 个请求。 -
-i <间隔秒数>
:指定每个请求之间等待的时间间隔(以秒为单位)。默认是 1 秒。 -
-f
:洪水模式(flood ping)。在这种模式下,ping
会尽可能快地发送数据包并显示结果。这种模式通常用于压力测试,普通用户不建议使用。 -
-q
:安静模式。只显示ping
命令的汇总统计信息,而不是每个数据包的应答。
netstat
netstat
用于查看网络状态,常用选项如下:
n
:显示IP地址而不限制主机名l
:列出在监听状态下的服务p
:显示建立该连接的程序名t
:只显示TCP
连接相关的服务u
:只显示UDP
连接相关的服务a
:显示所有服务,如果不带a,则只显示在当前终端启动的服务
常用的组合是:npua
和npta
:
使用npta
,展示的所有进程都是TCP
连接,但是由于我们没有root
权限,只能看到少量信息,此时可以sudo
提权:
此时最右侧的pragma name
显示出来了,这些就是使用TCP
的服务的名称,比如常见的数据库mysql
。