1. 项目概述
最近在开发一个基于C++的Socket通信系统时,遇到了不少坑。今天就把这个支持同步阻塞和异步非阻塞两种模式、能够处理多客户端连接的完整实现方案分享给大家。这个方案已经在VS2015环境下测试通过,可以直接用于实际项目开发。
这个Socket通信系统最大的特点是:
- 同时支持同步阻塞和异步非阻塞两种通信模式
- 服务端可以同时处理多个客户端连接
- 实现了智能断线重连机制
- 代码注释详细,逻辑清晰易懂
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 技术选型与考量
选择Windows Socket API(Winsock)作为基础通信框架主要基于以下几点考虑:
- 原生支持:Windows平台原生API,性能最优
- 灵活性:同时支持同步和异步两种编程模式
- 成熟稳定:经过多年发展,API稳定可靠
对于异步模式,我们采用WSAAsyncSelect模型而非IOCP,主要因为:
- 开发复杂度较低
- 与MFC消息机制天然契合
- 对于中小规模并发足够高效
2.2 核心组件设计
系统分为三个主要模块:
-
网络通信核心模块
- Socket创建与配置
- 连接管理
- 数据传输
-
协议处理模块
- 数据封包/解包
- 编码转换
- 心跳检测
-
用户界面模块
- 连接状态显示
- 消息收发界面
- 日志记录
3. 同步阻塞模式实现
3.1 服务端实现要点
同步阻塞模式下,服务端的主要工作流程如下:
cpp复制// 创建监听socket
SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// 绑定地址和端口
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("0.0.0.0");
service.sin_port = htons(DEFAULT_PORT);
bind(listenSocket, (SOCKADDR*)&service, sizeof(service));
// 开始监听
listen(listenSocket, SOMAXCONN);
// 接受客户端连接
SOCKET clientSocket = accept(listenSocket, NULL, NULL);
// 接收数据
char recvbuf[DEFAULT_BUFLEN];
int recvResult = recv(clientSocket, recvbuf, DEFAULT_BUFLEN, 0);
// 发送数据
send(clientSocket, sendbuf, (int)strlen(sendbuf), 0);
注意:同步模式下每个accept和recv都会阻塞线程,因此通常需要为每个客户端连接创建独立线程。
3.2 客户端实现要点
客户端同步模式实现相对简单:
cpp复制// 创建socket
SOCKET ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// 连接服务器
sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr(serverIP);
clientService.sin_port = htons(serverPort);
connect(ConnectSocket, (SOCKADDR*)&clientService, sizeof(clientService));
// 发送接收数据
send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
recv(ConnectSocket, recvbuf, DEFAULT_BUFLEN, 0);
3.3 同步模式优缺点分析
优点:
- 编程模型简单直观
- 代码逻辑清晰
- 调试方便
缺点:
- 每个连接需要独立线程
- 线程切换开销大
- 并发能力有限
4. 异步非阻塞模式实现
4.1 核心机制解析
异步模式采用事件驱动模型,通过WSAAsyncSelect将Socket事件与窗口消息绑定:
cpp复制// 注册感兴趣的网络事件
WSAAsyncSelect(m_Socket, m_hWnd, NETWORK_EVENT,
FD_CONNECT | FD_READ | FD_WRITE | FD_CLOSE);
当注册的事件发生时,系统会发送指定消息到窗口过程:
cpp复制BEGIN_MESSAGE_MAP(CAsyncSocketDlg, CDialogEx)
ON_MESSAGE(NETWORK_EVENT, OnNetworkEvent)
END_MESSAGE_MAP()
4.2 服务端详细实现
4.2.1 客户端管理
服务端使用链表结构管理所有客户端连接:
cpp复制typedef struct ClientInfo {
SOCKET socket;
sockaddr_in addr;
time_t lastActive;
// 其他客户端信息...
} ClientInfo;
std::list<ClientInfo> clientList;
4.2.2 消息处理流程
- 接受新连接:
cpp复制void CAsyncSocketDlg::OnAccept()
{
SOCKET clientSocket = accept(listenSocket, NULL, NULL);
// 设置非阻塞模
