网络编程基础
理解网络体系结构
OSI 七层模型
OSI(Open Systems Interconnection)七层模型是理论上的通信框架,由 ISO 提出。它将网络通信划分为七个层次,每一层都有特定的功能和协议:
- 物理层(Physical Layer):负责传输原始比特流(0 和 1),定义物理介质特性。
- 数据链路层(Data Link Layer):将比特流组织成帧,管理 MAC 地址和局域网通信。
- 网络层(Network Layer):负责数据包的路由和转发,使用 IP 地址标识设备。
- 传输层(Transport Layer):提供端到端的数据传输服务,确保可靠性和顺序。
- 会话层(Session Layer):管理通信会话的建立、维护和终止。
- 表示层(Presentation Layer):处理数据的格式转换,如加密、压缩。
- 应用层(Application Layer):直接为用户应用程序提供网络服务。
TCP/IP 四层模型
实际应用中广泛使用的是 TCP/IP 模型,由四层组成:
- 网络接口层:对应 OSI 的物理层和数据链路层。
- 网络层(Internet Layer):对应 OSI 的网络层,处理路由和寻址。
- 传输层(Transport Layer):对应 OSI 的传输层,提供端到端服务。
- 应用层(Application Layer):对应 OSI 的应用层、表示层和会话层。
主要区别与协议概述
- 层次划分:OSI 是理论模型(7 层),TCP/IP 是实用模型(4 层)。
- 协议支持:TCP/IP 是互联网的基础实现。
- HTTP:应用层协议,无状态,基于请求 - 响应模型。
- TCP:传输层协议,可靠、面向连接,通过三次握手建立连接。
- IP:网络层协议,无连接、不可靠,负责路由。
Socket 基础
Socket 概念与类型
Socket 是网络通信的基本操作单元,是对不同主机上应用进程之间双向通信端点的抽象。一个套接字由 IP 地址和端口号唯一标识。
流式套接字(SOCK_STREAM):基于 TCP,提供可靠、有序的数据传输,适合文件传输等场景。 数据报套接字(SOCK_DGRAM):基于 UDP,无连接,不保证可靠性,适合实时性要求高的应用。
Socket 地址结构
在 C++ 中,常用 sockaddr 及其衍生结构。
struct sockaddr {
unsigned short sa_family; // 地址家族,如 AF_INET
char sa_data[14]; // 协议地址
};
struct sockaddr_in {
short int sin_family; // 通常为 AF_INET
unsigned short sin_port; // 端口号
struct in_addr sin_addr; // IP 地址
char sin_zero[8]; // 填充字段
};
对于 IPv6,使用 sockaddr_in6 结构。
字节序转换
网络字节序是大端序(Big-Endian),主机字节序可能不同,需进行转换。
// 网络字节序转主机字节序(32 位)
uint32_t ntohl(uint32_t netlong);
// 主机字节序转网络字节序(16 位)
uint16_t htons(uint16_t hostshort);
// 字符串与网络地址转换
const char* inet_ntop(int af, const void* src, char* dst, socklen_t size);
int inet_pton(int af, const char* src, void* dst);
网络协议详解
TCP 协议特性
- 连接建立:三次握手(SYN -> SYN+ACK -> ACK)。
- 可靠传输:确认应答(ACK)、超时重传、序列号。
- 流量控制:滑动窗口机制,动态调整接收窗口大小。
UDP 协议特性
- 无连接:无需握手,开销小。
- 不可靠:不保证顺序或到达。
- 适用场景:音视频流媒体、在线游戏、DNS 查询。
C++ Socket 编程
基础 API
创建套接字 (socket)
int socket(int domain, int type, int protocol);
// domain: AF_INET (IPv4), AF_INET6 (IPv6)
// type: SOCK_STREAM (TCP), SOCK_DGRAM (UDP)
绑定套接字 (bind)
int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
监听连接 (listen)
int listen(int sockfd, int backlog);
接受连接 (accept)
int accept(int sockfd, struct sockaddr* addr, socklen_t *addrlen);
连接与数据传输
客户端使用 connect() 建立连接,send() 发送数据,recv() 接收数据。
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);
if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("connect failed");
}
char buffer[1024];
ssize_t bytes_received = recv(sockfd, buffer, sizeof(buffer), 0);
注意:返回值可能小于缓冲区长度,需循环读取直到完整数据到达。
高级 I/O 模型
阻塞与非阻塞 I/O
- 阻塞 I/O:数据未准备好时程序等待,简单但效率低。
- 非阻塞 I/O:立即返回错误(EWOULDBLOCK),需配合事件循环,适合高并发。
多路复用技术
允许单个线程监控多个文件描述符(fd)的状态变化。
| 特性 | select | poll | epoll |
|---|---|---|---|
| 最大 fd 数 | 有限 (FD_SETSIZE) | 无限制 | 无限制 |
| 效率 | O(n) | O(n) | O(1) |
| 内核支持 | 所有平台 | 所有平台 | Linux |
epoll 采用事件驱动,适合 Linux 下的高性能服务器。
并发编程
多线程与多进程
- 多线程:共享资源,轻量级,适合 I/O 密集型任务。需注意同步(如
std::mutex)。 - 多进程:资源隔离,稳定性高,适合 CPU 密集型或高可靠性场景。
线程池
维护一组工作线程,避免频繁创建销毁线程的开销。
class ThreadPool {
public:
ThreadPool(size_t threads);
template<class F, class... Args>
auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type>;
private:
std::vector<std::thread> workers;
std::queue<std::function<void()>> tasks;
std::mutex queue_mutex;
std::condition_variable condition;
bool stop;
};
应用层协议实现
HTTP 服务器开发
解析 HTTP 请求行(方法、URI、版本)和请求头,构建包含状态码、响应头和响应体的 HTTP 响应。
std::string BuildResponse(int status, const std::string& content) {
std::ostringstream response;
response << "HTTP/1.1 " << status << " OK\r\n";
response << "Content-Type: text/html\r\n";
response << "Content-Length: " << content.length() << "\r\n";
response << "\r\n";
response << content;
return response.str();
}
自定义协议设计
- 协议头:包含魔数、版本号、消息类型、序列号、消息体长度。
- 序列化:可使用 Protobuf 或 JSON。Protobuf 更高效,适合二进制传输。
网络安全与优化
SSL/TLS 基础
使用 OpenSSL 库实现加密通信,确保机密性和完整性。
SSL_CTX* ctx = SSL_CTX_new(TLS_server_method());
SSL_CTX_use_certificate_file(ctx, "server.crt", SSL_FILETYPE_PEM);
SSL* ssl = SSL_new(ctx);
SSL_set_fd(ssl, sockfd);
SSL_accept(ssl); // 服务器端
性能优化策略
- 零拷贝:使用
sendfile减少用户态与内核态拷贝。 - 缓冲区调整:设置
SO_RCVBUF和SO_SNDBUF。 - 禁用 Nagle 算法:设置
TCP_NODELAY减少延迟。
实践案例
经典网络应用
- 聊天服务器:基于 TCP,处理多客户端连接(结合线程池或 epoll)。
- 文件传输:分块传输,校验和验证,支持断点续传。
第三方库应用
- Boost.Asio:跨平台异步 I/O 库,基于 Proactor 模式。
- Protobuf:Google 开发的高效序列化格式,支持跨语言。
// Boost.Asio 异步连接示例
void async_connect(boost::asio::ip::tcp::socket& socket,
const boost::asio::ip::tcp::resolver::results_type& endpoints) {
boost::asio::async_connect(socket, endpoints,
[](boost::system::error_code ec, const auto& it) {
if (!ec) std::cout << "Connected!\n";
});
}


