Linux网络编程入门:UDP通信与网络基础
在学习 Linux 网络编程之前,我们需要先了解一些网络通信的基础概念,并掌握 Linux 中常用的网络配置命令。本文基于我的学习笔记,重点介绍网络分层模型、IP 地址、网络配置以及如何使用 UDP 协议进行简单的网络编程。
一、网络基础概念
1.1 什么是协议?
协议是通信双方约定的一套标准,它定义了数据格式、传输规则等,确保不同设备之间能够正确交换信息。
1.2 OSI 七层模型(理想模型)
OSI(Open System Interconnection)模型将网络通信划分为七层,每一层负责特定的功能:
| 7 | 应用层 | 提供网络服务,如 HTTP、FTP |
| 6 | 表示层 | 数据加密、解密、格式转换 |
| 5 | 会话层 | 建立、管理、终止会话 |
| 4 | 传输层 | 端到端的数据传输(TCP/UDP) |
| 3 | 网络层 | 路由选择、跨局域网通信(IP) |
| 2 | 数据链路层 | 局域网内部通信,MAC 地址 |
| 1 | 物理层 | 物理介质传输比特流 |
1.3 TCP/IP 模型(实际使用模型)
TCP/IP 模型是事实上的工业标准,它简化了 OSI 模型,分为四层:
-
应用层(对应 OSI 的应用层、表示层、会话层)
-
传输层
-
网络层
-
网络接口层(对应 OSI 的数据链路层和物理层)
下图展示了两种模型的对应关系:
text
OSI 模型 TCP/IP 模型
+———+ +———–+
| 应用层 | <–> | 应用层 |
| 表示层 | | |
| 会话层 | | |
+———+ +———–+
| 传输层 | <–> | 传输层 |
+———+ +———–+
| 网络层 | <–> | 网络层 |
+———+ +———–+
| 数据链路| <–> | 网络接口层|
| 物理层 | | |
+———+ +———–+
二、TCP/IP 协议族中的主要协议
2.1 应用层协议
-
HTTP:超文本传输协议,用于网页访问。
-
HTTPS:加密的 HTTP。
-
DNS:域名解析协议,将域名转换为 IP 地址。
-
TELNET:远程登录协议。
-
SMTP:邮件传输协议。
-
MQTT:物联网传输协议。
-
RTSP:流媒体协议。
2.2 传输层协议
-
UDP(用户数据报协议)
特点:资源开销小、传输机制简单、不安全不可靠。适用于实时性要求高但可容忍丢包的场景(如视频通话、DNS 查询)。 -
TCP(传输控制协议)
特点:资源开销大、机制复杂、可靠安全。通过三次握手建立连接、四次挥手释放连接,并具备确认机制、流量控制和拥塞控制。
2.3 网络层协议
-
IPv4:目前广泛使用的 IP 协议版本。
-
IPv6:下一代 IP 协议,解决地址耗尽问题。
-
ARP:地址解析协议,根据 IP 地址获取 MAC 地址。
-
RARP:逆地址解析协议,根据 MAC 地址获取 IP 地址。
跨局域网通信使用 IP 地址,局域网内部通信使用 MAC 地址。
三、IP 地址与子网掩码
3.1 IPv4 地址结构
一个 IPv4 地址由 32 位二进制组成,通常用点分十进制表示,例如 192.168.0.107。
IP 地址 = 网络位 + 主机位。
-
网段号:网络位不变,主机位全为 0。例如 192.168.0.0。
-
广播地址:网络位不变,主机位全为 1。例如 192.168.0.255。
-
子网掩码:用于区分网络位和主机位。掩码中为 1 的位对应网络位,为 0 的位对应主机位。
例如:
text
IP 地址: 192.168.0.107 → 11000000.10101000.00000000.01101011
子网掩码: 255.255.255.0 → 11111111.11111111.11111111.00000000
网络位: 192.168.0 主机位:107
同一网段内的 IP 地址可以直接通信。
3.2 IP 地址分类
| A | 1.0.0.0 ~ 126.255.255.255 | 255.0.0.0 | 超大规模网络 |
| B | 128.0.0.0 ~ 191.255.255.255 | 255.255.0.0 | 大中规模网络 |
| C | 192.0.0.0 ~ 223.255.255.255 | 255.255.255.0 | 中小规模网络 |
| D | 224.0.0.0 ~ 239.255.255.255 | 组播 | 组播通信 |
| E | 240.0.0.0 ~ 255.255.255.255 | 实验 | 科研实验 |
3.3 公有地址与私有地址
-
公有地址:可在互联网上路由,需向 ISP 申请。
-
私有地址:仅在局域网内使用,不能直接访问互联网。常见私有地址范围:
-
A 类:10.0.0.0 ~ 10.255.255.255
-
B 类:172.16.0.0 ~ 172.31.255.255
-
C 类:192.168.0.0 ~ 192.168.255.255
-
四、Linux 网络配置与常用命令
4.1 虚拟机网络模式
在虚拟机中,通常有两种工作模式:
-
桥接模式:Ubuntu 与主机网络独立,拥有真实独立的 IP 地址,可作为局域网服务器。
-
NAT 模式:Ubuntu 共享主机的网络,IP 地址由虚拟 DHCP 分配,无法作为服务器,但只要有网即可上网。
4.2 常用网络命令
ifconfig – 查看和配置网卡
bash
# 查看所有网卡信息
ifconfig
# 设置 ens33 网卡 IP 为 192.168.0.108/24,并启动
sudo ifconfig ens33 192.168.0.108/24 up
# 关闭/开启网卡
sudo ifconfig ens33 down
sudo ifconfig ens33 up
ifconfig 输出示例:
text
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.60.130 netmask 255.255.255.0 broadcast 192.168.60.255
inet6 fe80::20c:29ff:fe68:7564 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:68:75:64 txqueuelen 1000 (Ethernet)
RX packets 1045202 bytes 1481265089 (1.4 GB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 96092 bytes 6482276 (6.4 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ping – 测试网络连通性
bash
ping www.baidu.com
ping 8.8.8.8
4.3 配置 Ubuntu 网络(以桥接模式为例)
在虚拟机设置中,将网卡改为桥接模式,并指定桥接的物理网卡(如无线网卡)。
修改 /etc/network/interfaces 文件,设置为 DHCP 自动获取 IP:
text
auto lo
iface lo inet loopback
auto ens33
iface ens33 inet dhcp
重启网络或重启虚拟机:
bash
sudo shutdown -r now
测试 ping www.baidu.com 验证网络连通。
五、UDP 通信编程
UDP 是一种无连接的传输层协议,使用简单,适合实时通信。在 Linux 中,我们通过套接字(socket)进行 UDP 通信。
5.1 套接字创建 – socket()
c
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
-
domain:协议族,IPv4 使用 AF_INET。
-
type:套接字类型,UDP 使用 SOCK_DGRAM(数据报套接字)。
-
protocol:指定协议,UDP 对应 0。
-
返回值:成功返回新的文件描述符,失败返回 -1。
5.2 发送数据 – sendto()
c
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
-
sockfd:socket() 返回的文件描述符。
-
buf:要发送数据的缓冲区。
-
len:数据长度。
-
flags:通常为 0。
-
dest_addr:目标地址结构体指针(包含 IP 和端口)。
-
addrlen:目标地址结构体大小。
-
返回值:成功返回发送的字节数,失败返回 -1。
5.3 地址转换函数
由于网络字节序与主机字节序可能不同,我们需要进行转换:
-
htons():将 16 位主机字节序转换为网络字节序(常用于端口号)。
-
htonl():将 32 位主机字节序转换为网络字节序(常用于 IP 地址)。
-
inet_addr():将点分十进制 IP 字符串转换为 32 位网络字节序的整数。
例如:
c
struct sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_port = htons(8888); // 端口号
dest.sin_addr.s_addr = inet_addr("192.168.1.100"); // 目标 IP
5.4 一个简单的 UDP 发送端示例
下面是一个基于上述函数的 UDP 发送程序,它向指定 IP 和端口发送一条消息。
c
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
int main() {
// 1. 创建套接字
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket");
return 1;
}
// 2. 设置目标地址(接收端)
struct sockaddr_in dest_addr;
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(8888); // 接收端端口
dest_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 本机测试
// 3. 发送数据
char *msg = "Hello, UDP!";
int ret = sendto(sockfd, msg, strlen(msg), 0,
(struct sockaddr*)&dest_addr, sizeof(dest_addr));
if (ret < 0) {
perror("sendto");
close(sockfd);
return 1;
}
printf("发送了 %d 字节\\n", ret);
// 4. 关闭套接字
close(sockfd);
return 0;
}
注意:完整的 UDP 通信还需要接收端,接收端使用 recvfrom() 函数,本文基于笔记内容仅介绍发送函数,接收端原理类似。
六、总结
本文从网络协议基础出发,介绍了 OSI 和 TCP/IP 模型、IP 地址与子网掩码、Linux 网络配置命令,并重点讲解了 UDP 通信编程中几个关键函数的使用。掌握这些知识后,你可以进一步探索 TCP 编程、多线程并发服务器等更复杂的内容。
通过实践编写简单的 UDP 程序,并配合 ifconfig 和 ping 命令调试网络,能够帮助你快速入门 Linux 网络编程。





