以下是 Linux 网络系列 的核心内容总结:Linux 网络基础 + 网络编程(UDP Socket + TCP Socket)(以 2026 年视角,基于 Linux 内核 6.6+ 和 POSIX 标准)。内容聚焦实际编程视角,包含原理、关键 API、完整示例代码、对比分析及常见坑/优化建议。
1. Linux 网络基础快速回顾
| 概念 | 说明 | 关键协议/模型 |
|---|---|---|
| 协议栈 | 应用层 → 传输层 → 网络层 → 数据链路层 | TCP/IP 模型 |
| Socket 类型 | SOCK_STREAM(TCP,有序、可靠、面向连接) SOCK_DGRAM(UDP,无连接、不可靠) | socket(2) 参数 |
| 地址族 | AF_INET(IPv4)、AF_INET6(IPv6)、AF_UNIX(本地 IPC) | sockaddr 族 |
| 字节序 | 网络字节序(大端) vs 主机字节序(小端) | htons/ntohs, htonl/ntohl |
| 常用系统调用 | socket → bind → listen → accept(服务器) socket → connect(客户端) send/recv, sendto/recvfrom | man 2 socket |
现代趋势(2026):
- io_uring 异步 I/O 取代 select/poll/epoll 的主流选择
- eBPF 用于 Socket 过滤、XDP 加速
- 但基础 Socket API 几乎不变,仍是学习起点
2. UDP Socket 编程(无连接、数据报)
特点:
- 无连接(无需三次握手)
- 不可靠(丢包、重包、乱序都可能)
- 高效、低延迟(适合实时音视频、DNS、游戏)
- 每个数据报独立(带地址信息)
核心 API:
- socket(AF_INET, SOCK_DGRAM, 0)
- bind()(服务器通常需要,客户端可选)
- sendto() / recvfrom()(必须带地址)
UDP 服务器(回显示例)
// udp_server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define PORT 8888
#define BUFLEN 1024
int main(void) {
int sockfd;
struct sockaddr_in servaddr, cliaddr;
char buf[BUFLEN];
socklen_t len = sizeof(cliaddr);
// 创建 UDP socket
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// 清零并填充服务器地址
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
// 绑定
if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
printf("UDP server listening on port %d...\n", PORT);
while (1) {
// 接收数据(阻塞)
int n = recvfrom(sockfd, buf, BUFLEN-1, 0, (struct sockaddr *)&cliaddr, &len);
if (n < 0) continue;
buf[n] = '\0';
printf("Received from %s:%d → %s\n",
inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port), buf);
// 回显
sendto(sockfd, buf, n, 0, (struct sockaddr *)&cliaddr, len);
}
close(sockfd);
return 0;
}
UDP 客户端(发送 → 接收回显)
// udp_client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define SERVER_IP "127.0.0.1"
#define PORT 8888
#define BUFLEN 1024
int main(void) {
int sockfd;
struct sockaddr_in servaddr;
char buf[BUFLEN];
char *message = "Hello UDP Server!";
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
inet_pton(AF_INET, SERVER_IP, &servaddr.sin_addr);
// 发送
sendto(sockfd, message, strlen(message), 0,
(struct sockaddr *)&servaddr, sizeof(servaddr));
// 接收回显(可选超时)
int n = recvfrom(sockfd, buf, BUFLEN-1, 0, NULL, NULL);
if (n > 0) {
buf[n] = '\0';
printf("Server replied: %s\n", buf);
}
close(sockfd);
return 0;
}
编译运行:
gcc udp_server.c -o udp_server
gcc udp_client.c -o udp_client
./udp_server &
./udp_client
3. TCP Socket 编程(面向连接、可靠传输)
特点:
- 三次握手、四次挥手
- 可靠、有序、流量控制、拥塞控制
- 流式(无消息边界)
核心 API:
- socket(AF_INET, SOCK_STREAM, 0)
- bind → listen → accept(服务器)
- connect(客户端)
- send/recv(或 write/read)
TCP 服务器(回显 + 支持多客户端)
// tcp_server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define PORT 8888
#define MAX_CLIENTS 10
#define BUFLEN 1024
int main(void) {
int server_fd, client_fd;
struct sockaddr_in servaddr, cliaddr;
socklen_t len = sizeof(cliaddr);
char buf[BUFLEN];
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) { perror("socket"); exit(1); }
int opt = 1;
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
if (bind(server_fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
perror("bind"); exit(1);
}
if (listen(server_fd, 5) < 0) { perror("listen"); exit(1); }
printf("TCP server listening on port %d...\n", PORT);
while (1) {
client_fd = accept(server_fd, (struct sockaddr *)&cliaddr, &len);
if (client_fd < 0) { perror("accept"); continue; }
printf("New client: %s:%d\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
// 简单回显(单线程处理一个客户端)
while (1) {
int n = recv(client_fd, buf, BUFLEN-1, 0);
if (n <= 0) break;
buf[n] = '\0';
printf("Received: %s", buf);
send(client_fd, buf, n, 0);
}
close(client_fd);
printf("Client disconnected\n");
}
close(server_fd);
return 0;
}
TCP 客户端
// tcp_client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define SERVER_IP "127.0.0.1"
#define PORT 8888
#define BUFLEN 1024
int main(void) {
int sockfd;
struct sockaddr_in servaddr;
char buf[BUFLEN];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) { perror("socket"); exit(1); }
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
inet_pton(AF_INET, SERVER_IP, &servaddr.sin_addr);
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
perror("connect"); exit(1);
}
printf("Connected to server. Type messages (empty line to quit):\n");
while (fgets(buf, BUFLEN, stdin) != NULL) {
if (buf[0] == '\n') break;
send(sockfd, buf, strlen(buf), 0);
int n = recv(sockfd, buf, BUFLEN-1, 0);
if (n > 0) {
buf[n] = '\0';
printf("Server: %s", buf);
}
}
close(sockfd);
return 0;
}
4. UDP vs TCP 核心对比(面试/设计必备)
| 维度 | UDP | TCP |
|---|---|---|
| 连接 | 无连接 | 面向连接(三次握手) |
| 可靠性 | 不可靠(丢包、重包、乱序) | 可靠(确认、重传、排序) |
| 传输单位 | 数据报(有边界) | 字节流(无边界) |
| 开销 | 低(8 字节头部) | 高(20+ 字节头部 + 控制报文) |
| 适用场景 | DNS、DHCP、视频流、游戏 | HTTP、FTP、SMTP、数据库 |
| 性能(延迟/吞吐) | 低延迟、高吞吐(但丢包时无重传) | 高可靠性,但延迟较高 |
| 编程复杂度 | 简单(sendto/recvfrom) | 复杂(accept、close 优雅处理) |
5. 进阶 & 2026 实用建议
- 多客户端处理:
- TCP:多进程(fork)、多线程、select/poll/epoll、io_uring
- UDP:单线程 + epoll 即可(无连接状态)
- 推荐现代 API:
- getaddrinfo() / getnameinfo() 代替 inet_pton + 硬编码
- setsockopt(SO_REUSEADDR, SO_REUSEPORT)
- 非阻塞 + epoll(高并发首选)
- 常见坑:
- UDP:忘记 bind → 无法接收;忘记清零 sockaddr → 垃圾数据
- TCP:忘记 close() → 端口占用;半关闭(shutdown)处理不当
- 字节序:忘记 htons → 端口错乱
- 性能优化:
- UDP:增大 socket 接收缓冲区(setsockopt SO_RCVBUF)
- TCP:Nagle 关闭(TCP_NODELAY)、keep-alive、SO_LINGER
- 安全:
- 校验和、长度检查、防 DDoS(rate limit)
- 使用 libsodium / OpenSSL 加密
如果你想深入某个方向(epoll 版服务器、UDP 多播、io_uring 异步、QUIC 初步、Unix Domain Socket 对比),随时告诉我,我可以继续展开!