前言
在网络编程的世界里,TCP/IP 协议是构建一切网络应用的基石。本节将从应用层到传输层,逐步拆解 HTTP、UDP、TCP 等核心协议,并结合实践案例帮助你建立系统的理解。这不仅是网络编程的理论基础,也是服务端开发的必备技能,更是各大公司笔试、面试的高频考点。
一、应用层:人与网络的接口
1. 什么是应用层
应用层是用户与网络通信最直接的接口。程序员编写的各种网络应用(浏览器、聊天软件、在线游戏等)都工作在这一层。
2. 协议的本质
协议就是通信双方约定的数据格式与处理规则。例如,Socket API 传输的本质是字符串,但如果需要传输结构化数据,就需要序列化 与反序列化来保证双方能正确解析数据。
3. 网络版计算器示例
方案一:直接发送字符串
c
// 客户端发送
write(fd, "1+1", 3);
// 服务端解析
char buf[10];
read(client_fd, buf, sizeof(buf));
方案二:使用结构体 + 序列化
c
typedef struct Request {
int a;
int b;
} Request;
typedef struct Response {
int sum;
} Response;
4. HTTP 协议简介
HTTP 是最常用的应用层协议,主要特点:
- 请求格式:首行(方法、URL、版本)、Header(键值对)、Body(可为空)。
- 响应格式:首行(版本、状态码、解释)、Header、Body。
- 常用方法:GET、POST。
- 常见状态码:200、404、403、302、504。
- 常用 Header:Content-Type、Content-Length、Host、User-Agent、Referer、Cookie 等。
5. 最简单的 HTTP 服务器
c
const char* hello = "<h1>Hello World</h1>";
sprintf(buf, "HTTP/1.0 200 OK\nContent-Length:%lu\n\n%s", strlen(hello), hello);
write(client_fd, buf, strlen(buf));
浏览器访问 http://[ip]:[port]
即可看到页面。
二、传输层:数据传输的保障
1. 端口号
端口号用于区分同一主机上的不同应用程序:
- 0--1023:知名端口(如 HTTP:80, HTTPS:443)。
- 1024--65535:动态分配端口。
2. 常用工具
- netstat:查看网络连接与端口状态。
bash
netstat -nltp
- pidof:通过进程名查找 PID。
bash
pidof nginx
三、UDP 协议:轻量但不可靠
1. 特点
- 无连接
- 不保证可靠性
- 面向数据报(不会拆分/合并数据)
2. 应用
适用于实时性要求高、允许丢包的场景,如视频传输、DNS、在线游戏等。
四、TCP 协议:可靠传输的代表
1. 核心机制
- 确认应答(ACK)
- 超时重传
- 三次握手 / 四次挥手(连接管理)
- 滑动窗口(提高性能)
- 流量控制(防止接收端过载)
- 拥塞控制(避免网络拥堵)
- 延迟应答、捎带应答(优化传输效率)
2. 特殊状态解析
- TIME_WAIT:等待 2MSL 确保延迟包消失。
- CLOSE_WAIT:服务端未正确关闭 socket 导致的状态堆积。
3. 粘包问题
由于 TCP 是面向字节流的协议,接收端无法自动识别应用层包的边界,需要应用层自己定义分隔方式。
五、TCP 与 UDP 对比
特性 | TCP | UDP |
---|---|---|
可靠性 | 高(确认应答、重传) | 低(可能丢包) |
连接方式 | 面向连接 | 无连接 |
速度 | 较慢 | 快 |
适用场景 | 文件传输、重要消息 | 实时通信、视频流 |
六、实验与调试工具
1. listen 参数的影响
listen
的第二个参数影响全连接队列长度,过小可能导致 SYN_RECV 状态连接积压。
2. Wireshark 抓包
通过过滤器观察 TCP 三次握手、四次挥手及数据传输过程:
text
tcp.port == 9090
总结
TCP/IP 协议不仅是网络通信的基础,更是程序员必须掌握的核心技能。掌握它的原理和使用方法,不仅能写出高性能网络程序,还能在定位、调试网络问题时游刃有余。