网络基础
1. 发展历程
-
独立模式:早期计算机相互独立,数据无法共享。用户需在特定终端上操作,导致资源利用率低和协作困难(如例子中小松、小竹、小梅需等待特定终端)。
-
网络互联:多台计算机连接在一起,实现数据共享和协同工作。数据由服务器集中管理,用户可从任意终端接入,提升了效率和灵活性。
-
局域网 (LAN):覆盖较小地理范围,通过交换机和路由器连接本地计算机。
-
广域网 (WAN):覆盖广阔地理范围,连接不同地域的局域网(如连接大阪、东京、洛杉矶的网络)。
计算机作为人类协作的工具,其网络化是必然趋势。“局域网”与“广域网”是相对概念。
2.网络协议基础
2.1 什么是协议?
-
定义:协议是一种通信双方共同遵守的“约定”或“标准”。它规定了数据的格式、传输方式和处理逻辑,确保不同厂商、不同操作系统的计算机能够顺畅通信。
-
必要性:
-
计算机通过光/电信号(频率和强弱)表示
0和1。 -
若双方仅约定格式但编码方式不同(如一个用频率表示
01,一个用强弱表示01),则无法通信。 -
因此,需要一个被业界普遍认可的组织(如IEEE、ISO、IETF)来制定统一、细致的标准,即网络协议。
-
-
朴素理解:从软件实现角度看,协议可以理解为通信双方都认识的结构化数据类型。例如,主机A和主机B都定义了相同的
struct protocol,双方发送和接收该结构体数据时就能准确解析其字段(如a=10,b=20,c=30)。
2.2 协议分层
-
分层思想:协议本质是复杂的软件,采用分层设计可以解耦合,使各层独立发展、易于维护。上层只需调用下层提供的服务接口,无需关心其内部实现。
-
类比说明:
-
语言层(应用层):负责沟通内容(如汉语、英语),变更语言不影响通信设备。
-
通信设备层(物理/链路层):负责信号传输(如电话、无线电),变更设备不影响沟通语言。
-
2.3 OSI 七层模型 vs. TCP/IP 五层模型
-
OSI 七层模型:一个逻辑上完善但复杂的参考模型(应用层、表示层、会话层、传输层、网络层、数据链路层、物理层)。
-
TCP/IP 五层模型:工业界实际采用的标准,更实用。通常也将最底层的物理层和数据链路层视为一层,因此也常被称为四层模型。

| TCP/IP 分层 | 主要功能 | 常见协议/设备 | OSI 对应层 |
|---|---|---|---|
| 应用层 | 负责特定应用程序间的通信。 | HTTP, HTTPS, FTP, SMTP, DNS, SSH | 应用层、表示层、会话层 |
| 传输层 | 负责端到端(进程到进程)的可靠或不可靠数据传输。 | TCP, UDP | 传输层 |
| 网络层 | 负责地址管理(逻辑寻址)和路由选择(规划传输路径)。 | IP, ICMP, ARP,路由器 | 网络层 |
| 数据链路层 | 负责相邻节点间数据帧的传输和识别(物理寻址)。 | 以太网协议,交换机,MAC地址 | 数据链路层 |
| 物理层 | 负责将比特流转换为物理信号(光/电/电磁波)进行传输。 | 网线、光纤、无线信号,集线器 | 物理层 |
操作系统内核通常实现传输层到物理层(或数据链路层)。
路由器实现网络层到物理层。
交换机实现数据链路层到物理层。
集线器仅实现物理层。
3. 网络传输流程
3.1 数据封装与解包


-
封装 (Encapsulation):数据从应用层向下传递时,每一层都会在原始数据前添加自己的协议报头 (Header)。
-
解包 (Decapsulation):数据到达目标主机后,从物理层向上传递,每一层会剥离对应的报头,并根据报头信息将有效载荷交付给上层协议处理。
-
报文结构:报文 = 协议报头 + 有效载荷 (Payload)
-
不同层的协议数据单元 (PDU):
-
应用层:数据 (Data)
-
传输层:数据段 (Segment)
-
网络层:数据包/数据报 (Packet / Datagram)
-
数据链路层:数据帧 (Frame)
-
物理层:比特流 (Bits)
-
数据封装过程
数据分用过程

3.2 局域网通信原理
-
MAC地址 (Media Access Control Address):
-
长度 48 位(6 字节),通常用十六进制表示(如
08:00:27:03:fb:19)。 -
在网卡出厂时固化,全球唯一(理想情况下)。
-
作用:在局域网(数据链路层)中唯一标识一个网络接口,用于帧的精确投递。
-
-
通信过程:

-
主机A向主机E发送数据帧,帧头包含 源MAC地址(MacA) 和 目标MAC地址(MacE)。
-
该数据帧会被广播到局域网内所有主机。
-
主机B、C、D收到帧后,检查目标MAC地址与自身不符,直接丢弃。
-
主机E收到帧后,发现目标MAC地址是自身,则接收并处理。
-
-
以太网特性:
-
同一时刻只允许一台主机发送数据。
-
多台主机同时发送会导致数据碰撞,此时主机需执行碰撞避免算法,等待随机时间后重发。
-
没有交换机时,一个以太网就是一个碰撞域(共享资源,具有互斥性)。
-
3.3 跨网络通信流程

-
IP地址 (Internet Protocol Address):
-
在IPv4中,长度为 32 位(4 字节)。
-
常用“点分十进制”表示(如
192.168.0.1)。 -
作用:在全球范围内(网络层)逻辑上唯一标识一台主机,是实现跨网络通信和路由选择的关键。
-
区分MAC地址:
-
IP地址是长远目标,在端到端传输中保持不变(此处为简化理解),用于全局路由决策。
-
MAC地址是下一阶段目标,在每一段局域网传输中会改变,用于本地帧转发。
-
-
-
通信步骤:
-

-
主机A(
192.168.2.2)判断目标主机B(172.168.2.2)不在同一网段。 -
主机A将IP数据包封装成帧,目标MAC地址写为默认网关/路由器接口的MAC地址(MacLeft),发往路由器。
-
路由器收到帧后,解包到网络层,查看目标IP地址,查询路由表决定下一跳路径。
-
路由器将IP数据包重新封装成帧,源MAC地址改为自身出口的MAC地址(MacRight),目标MAC地址改为下一跳(可能是目标主机B或下一个路由器)的MAC地址,然后转发。
-
重复步骤3、4,直至数据包到达目标主机B。
-
主机B层层解包,最终将数据交付给应用进程。
-

IP网络层的核心意义:通过定义统一的IP协议和IP地址,屏蔽了下层各种异构网络(以太网、令牌环网、无线LAN等)的差异,向上层提供一个统一的、虚拟化的“IP网络”视图。
4. Socket 编程基础
4.1 网络通信的本质:进程间通信 (IPC)
4.1.1 为什么 IP 寻址到主机还不够?
-
观点:数据传输到主机不是目的,而是手段。数据是给人用的,而人在系统中通过进程(QQ、浏览器等)来获取数据。
-
结论:网络通信的本质是进程间通信。网络层负责将数据送到目标主机,传输层则负责将数据交付给具体的进程。
4.1.2 端口号 (Port)
-
定义:一个 2 字节 16 位的整数,用于在该主机内唯一标识一个网络进程。
-
IP + Port:
-
IP:标识全网内唯一的一台主机。
-
Port:标识该主机内唯一的一个网络进程。
-
Socket(套接字) = IP + Port,可标识全网内唯一的进程。
-
-
四元组:
{src_IP, src_Port, dst_IP, dst_Port}唯一标识了互联网中通信的两个进程。
4.1.3 端口号 vs 进程 PID
-
相同点:在各自范畴内都能唯一标识进程。
-
不同点:
-
不是所有进程都需要网络通信(不需要端口),但所有进程都有 PID。
-
解耦:PID 是操作系统内部管理的标准,如果网络直接使用 PID,一旦系统进程管理逻辑变化,网络部分也要随之重构。使用端口号可以实现系统管理与网络协议的解耦。
-
-
对应关系:一个进程可以绑定多个端口号,但一个端口号只能被一个进程占用。
4.2 传输层协议:TCP 与 UDP
网络功能属于 OS 内核。用户必须通过系统调用访问传输层功能。
| 特性 | TCP (传输控制协议) | UDP (用户数据报协议) |
|---|---|---|
| 连接性 | 有连接 | 无连接 |
| 可靠性 | 可靠传输(重传、排序等) | 不可靠传输 |
| 传输形式 | 面向字节流 | 面向数据报 |
| 特点 | 复杂、占用资源较多 | 简单、高效 |
4.3 网络字节序
-
内存 vs 网络:
-
主机可能有大端(高位存低地址)或小端(低位存低地址)之分。
-
网络规定:所有发送到网络的数据必须采用大端字节序。
-
-
规则:先发出的数据是低地址,后发出的是高地址。
4.3.1 字节序转换函数
#include <arpa/inet.h>uint32_t htonl(uint32_t hostlong); // 主机 -> 网络 (Long)uint16_t htons(uint16_t hostshort); // 主机 -> 网络 (Short)uint32_t ntohl(uint32_t netlong); // 网络 -> 主机 (Long)uint16_t ntohs(uint16_t netshort); // 网络 -> 主机 (Short)注:h 代表 host,n 代表 network,l 代表 32 位(IP),s 代表 16 位(Port)。
4.4 Socket 编程接口与数据结构
4.4.1 通用地址结构:struct sockaddr
为了统一接口(支持 IPv4、IPv6、本地通信 Unix Domain Socket),Socket API 采用了类似“继承与多态”的设计:
-
struct sockaddr:通用接口结构(16 位地址类型 + 14 字节地址数据)。 -
struct sockaddr_in:用于 IPv4 网络通信。 -
struct sockaddr_un:用于 Unix 域(本地)通信。
关键点:编程时使用特定的结构体(如
sockaddr_in),但在调用系统接口(如bind,accept)时,需要强制类型转换为struct sockaddr*。OS 会通过前 16 位的family类型来识别具体的协议。
4.4.2 数据结构 (IPv4)
struct in_addr { in_addr_t s_addr; // 32位 IP 地址 (网络字节序)};
struct sockaddr_in { sa_family_t sin_family; // 地址族,如 AF_INET in_port_t sin_port; // 16位端口号 (网络字节序) struct in_addr sin_addr; // 32位IP地址 unsigned char sin_zero[8]; // 填充,保证与 sockaddr 等大};4.5 常见 Socket API
4.5.1 通用接口(客户端与服务器均需)
socket():创建通信端点
int socket(int domain, int type, int protocol);-
功能:打开一个网络文件。在 Linux 中“一切皆文件”,该函数返回一个文件描述符(fd),后续所有操作都基于这个 fd。
-
参数:
-
domain:协议族。常用AF_INET(IPv4)或AF_INET6(IPv6)。 -
type:通信类型。常用SOCK_STREAM(面向连接的 TCP)或SOCK_DGRAM(面向数据报的 UDP)。 -
protocol:默认为 0,系统会根据type自动选择(如 TCP 或 UDP)。
-
-
返回值:成功返回非负整数 fd,失败返回 -1。
4.5.2 服务器端专属接口
bind():关联地址与端口
int bind(int socket, const struct sockaddr *address, socklen_t address_len);-
功能:将创建好的 socket 和物理层面的 IP 地址与端口号(Port)进行绑定。
-
注意:服务器必须绑定,否则客户端无法找到它;参数
address传入时通常需要将sockaddr_in强转为sockaddr。
listen():设置监听状态
int listen(int socket, int backlog);-
功能:将 socket 状态设置为
LISTEN,表示该服务器准备好接收来自客户端的连接请求。 -
参数:
backlog是全连接队列的最大长度,决定了系统能同时处理多少个等待中的连接请求。
accept():获取新连接
int accept(int socket, struct sockaddr* address, socklen_t* address_len);-
功能:从底层连接队列中取出一个已完成的连接。
-
返回值:非常重要。它返回一个新的文件描述符,专门用于和当前这个特定的客户端进行通信。
-
原有的监听套接字(Listen Socket)继续负责接收新连接。
-
返回的已连接套接字(Connected Socket)负责具体的数据交互。
-
4.5.3 客户端专属接口
connect():发起连接
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);-
功能:客户端通过此接口向服务器发起“三次握手”请求。
-
注意:客户端通常不需要显式 bind。在调用
connect时,操作系统会自动为客户端分配一个可用的随机端口。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!

