入门计算机网络:从局域网到 Socket 编程

这篇博客解决什么问题

刚接触网络编程时,你是不是一看到“TCP/IP协议簇”、“OSI七层模型”、“封装解包”这些词就头皮发麻?很多同学虽然会写代码,但对于数据究竟是怎么从自己的电脑跨越千山万水到达服务器的,往往只有一个模糊的概念。
这篇博客将带你梳理计算机网络的基础概念。我们不背八股文,而是顺着网络发展的脉络,搞懂局域网通信、跨网段传输的原理,最后顺利过渡到 Socket 编程的核心预备知识。看完这篇,你就能搭建起网络通信的宏观认知框架。


核心概念速览

  • 局域网 (LAN) & 广域网 (WAN):小范围互联与大范围互联的相对概念。
  • 协议 (Protocol):通信双方都认识的“结构化的数据类型”或“约定”。
  • 分层模型:OSI 七层(理论)与 TCP/IP 五层/四层(实际落地)。
  • MAC 地址 & IP 地址:物理设备的唯一标识(下一跳目标) vs 网络中的唯一标识(长远目标)。
  • 端口号 (Port):用于区分主机上不同进程的标识。
  • Socket:IP + Port,网络编程的套接字。

1. 网络是怎么来的?

计算机最初是独立模式,各自持有数据。后来为了协同工作与数据共享,产生了网络互联。随着计算机增多,通过交换机和路由器连接形成了局域网 (LAN);而将远隔千里的计算机连在一起,就成了广域网 (WAN)。实际上,局域网和广域网只是一个相对概念。

2. 什么是协议?为什么要分层?

协议就是一种约定。就像打电话前约定“响几声算挂断”一样。在网络中,不同厂商、不同操作系统的硬件林立,要想顺畅通信,就必须约定好统一的数据格式。

  • 为什么分层:软件设计中为了模块化、解耦合,网络协议被设计成了层状结构。
  • OSI 七层 vs TCP/IP 五层:OSI 是理论上的七层(物理、数据链路、网络、传输、会话、表示、应用),但在工程实践中,会话层和表示层很难在操作系统内核中落地,最终落地的是 TCP/IP 五层(或四层)模型。
层号OSI 七层模型TCP/IP 五层模型核心功能与代表设备/协议
7应用层应用层针对特定应用的协议(如 HTTP, FTP, SMTP)。
6表示层(实际工程中并入应用层)
5会话层(实际工程中并入应用层)
4传输层传输层负责两端主机间的数据传输,如 TCP, UDP。
3网络层网络层地址管理与路由选择,如 IP 协议,设备代表:路由器。
2数据链路层数据链路层设备间数据帧的传送与识别,设备代表:交换机。
1物理层物理层光电信号的传递方式,设备代表:集线器、网线。

注:一台主机的操作系统内核通常实现了从传输层到物理层;路由器实现了网络层到物理层;交换机实现了数据链路层到物理层。

3. 局域网通信原理:MAC 地址与碰撞

在同一局域网(如以太网)中,主机如何确认数据是发给自己的?
每台主机都有一个唯一的 MAC 地址(48位,出厂即固定)。主机 A 发送数据时,会带上目标 MAC 地址。由于以太网是广播机制,局域网内所有主机都能收到,但只有发现目标 MAC 和自己匹配的主机,才会接收数据。

注意:以太网中任何时刻只允许一台机器发送数据,如果多台同时发送,会发生数据碰撞。因此发送数据的主机需要进行碰撞检测和碰撞避免。

4. 跨网络传输原理:IP 地址与路由器

当我们要把数据发送给远方的朋友,光靠 MAC 地址就不行了(因为 MAC 地址只在局域网内有效)。这时就需要 IP 地址(IPv4是 4 字节,32 位整数,点分十进制表示)。

  • IP 地址:标识网络中不同主机的地址,在整个路由过程中一直不变(长远目标)。
  • MAC 地址:在跨网段传输时,源 MAC 和目的 MAC 会一直在变(下一跳目标)。

过程解析:数据先自顶向下封装,到达网络层后,路由器会解包发现目标 IP 不在本局域网,就会重新封装下一跳的 MAC 地址,将数据转发给下一个路由器。这就是 IP 网络层的意义:提供网络虚拟层,屏蔽最底层网络的差异。

5. 网络通信的终点:端口与进程

数据到达目的主机就是终点了吗?错!数据最终是给人用的(如聊天、下载),而人通过进程(QQ、微信、浏览器)来获取数据。因此,通信的本质是进程间通信。

  • 端口号 (Port):传输层协议的内容,2字节16位整数,用来标识主机上唯一的进程。一个端口号只能被一个进程占用,但一个进程可以绑定多个端口号。(为了防止系统进程管理与网络强耦合,端口号不采用 PID)。

6. 数据封装与解包

数据在网络中传输,不是直接发过去的,而是层层“穿衣”和“脱衣”。

  • 封装:发送方自上向下,每层加上自己的报头(Header)。
  • 解包/分用:接收方自下向上,每层剥去报头,根据报头中的“上层协议字段”将数据交给对应的上层处理。
  • 报文 = 报头 + 有效载荷。

动手示例:代码/命令/配置及说明

1. 网络字节序与转换函数

网络中传输数据规定使用大端字节序(低地址存高字节)。如果你的主机是小端机,就需要转换:

#include <arpa/inet.h>

// h代表host(主机),n代表network(网络),l代表32位长整数,s代表16位短整数
uint32_t htonl(uint32_t hostlong); // 32位主机字节序 -> 网络字节序
uint16_t htons(uint16_t hostshort); // 16位主机字节序 -> 网络字节序
uint32_t ntohl(uint32_t netlong); // 32位网络字节序 -> 主机字节序
uint16_t ntohs(uint16_t netshort); // 16位网络字节序 -> 主机字节序

2. Socket 编程常见 API(C语言)

// 创建 socket 文件描述符(TCP/UDP,客户端 + 服务器)
int socket(int domain, int type, int protocol);

// 绑定端口号(TCP/UDP,服务器)
int bind(int socket, const struct sockaddr *address, socklen_t address_len);

// 开始监听 socket (TCP, 服务器)
int listen(int socket, int backlog);

// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr * address, socklen_t * address_len);

// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

注意:sockaddr_in 结构体是 IPv4 专属的,包含地址类型(AF_INET)、端口号和 IP 地址。实际编程中,由于 socket 接口要兼容多种协议,统一用 struct sockaddr* 指针做参数,使用时再强转为 sockaddr_in。


注意事项

  1. 混淆 MAC 地址和 IP 地址的作用:记住,IP 是长远目标(终点),MAC 是下一阶段目标(每一跳)。IP 寻路,MAC 局域网内寻机。
  2. 忽略了网络字节序:所有发送到网络上的数据,都必须是大端的!写网络程序时,如果发现端口号或 IP 解析乱码,大概率是忘了用 htons() 转换。
  3. 认为进程 PID 就是端口号:虽然都有唯一性,但 PID 是系统概念。如果用 PID 标识网络,会导致系统进程管理和网络强耦合,所以网络通信单独设计了“端口号”。

总结

网络通信的本质是进程间通信。我们通过分层模型(TCP/IP)将复杂问题解耦;通过 IP 和端口(Socket)定位互联网上的唯二进程;数据在传输过程中通过反复封装和解包,最终准确交付给目标。

延伸阅读

  • 标准化组织:IEEE(制定了 IEEE802 系列局域网标准)、ISO(提出 OSI 模型)、IETF(负责开发和推广 TCP/IP 协议,通过 RFC 发布标准)。
  • 传输层协议对比:
    • TCP:有连接、可靠传输、面向字节流。
    • UDP:无连接、不可靠传输、面向数据报。
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐