1、C++SOCKET同步阻塞、异步非阻塞通信服务端、客户端代码,支持多个客户端连接
1、C++SOCKET同步阻塞、异步非阻塞通信服务端、客户端代码,支持多个客户端连接。 2、断线重连(服务端或客户端没有启动顺序要求,先开启的等待另一端连接); 3、服务端支持同时连接多个客户端; 4、阅读代码就明白通信道理,注释详细; 5、VS2015编译通过。
AsyncSocketTCP 源码级功能说明书
(基于 MFC 的异步非阻塞 TCP 群聊框架)
一、定位与目标
1.1 场景
桌面局域网内多客户端即时通讯演示,可作为 Windows 平台“最小可运行”的异步 IO 教学原型。
1.2 设计目标
- 零阻塞:UI 线程永不因网络 IO 卡顿。
- 零耦合:业务(聊天)与通信层通过 Windows 消息解耦。
- 零拷贝展示:服务器端一次接收、多次分发,避免内存复制带来的延迟。
二、总体架构
┌---------------- AsyncSocketTCP(Server)
│ WSAAsyncSelect
│ FD_ACCEPT / FD_READ / FD_CLOSE
▼
┌---------------------┐
│ 主对话框(UI 线程) │
│ OnNetworkControl │
│ OnActureControl │
└---------------------┘
▲
│ WM_USER+102/103
│
┌---------------------┐
│ 客户端对象链表 │
│ SOCKET + IP + PORT │
└---------------------┘
客户端采用对称设计,仅维护单个 SOCKET,通过 WSAAsyncSelect 回传 FDREAD/FDCLOSE 到主窗口。
三、关键技术点
3.1 异步 IO 模型
- 选用 WSAAsyncSelect 而非完成端口或重叠 IO,理由:
– 代码量最小,适合教学。
– 与 MFC 消息泵天然融合,无需额外工作线程。 - 两条自定义消息
NETWORKCONTROL(服务器监听套接字事件)
ACTURECONTROL(已连接套接字数据事件)
3.2 资源自管理
- 服务器端使用 std::list 保存已连接套接字,插入/删除时间复杂度 O(1)。
- 收到 FD_CLOSE 时立即从链表移除,再 closesocket,防止“已关闭句柄”复用 bug。
3.3 字符集自适应
- 工程属性可切换 Unicode/MBCS;内部通过 MultiByteToWideChar / WideCharToMultiByte 自动适配,保证中文路径、昵称不乱码。
3.4 流量控制策略
- 服务器在 FD_READ 中只做 recv,不直接 send,避免“嵌套调用”导致的栈溢出。
- 广播时遍历链表顺序发送,若返回 WSAEWOULDBLOCK 则直接丢弃,不做重试,保持轻量。
3.5 退出时序
- 客户端输入 Bye/Quit/886 后,先发送再 Sleep(1000) 给对端留缓冲时间,随后主动 closesocket,确保 TCP 四次挥手完整。
四、运行流程
4.1 启动服务器
- 点击“开始服务”→InitNetwork()→WSAStartup→socket→bind→listen→WSAAsyncSelect。
- 窗口收到 FDACCEPT→accept 生成新套接字→插入链表→对该套接字再次 WSAAsyncSelect(ACTURECONTROL)。
4.2 客户端接入
- 启动客户端→点击“连接”→initnetwork()→socket→connect→WSAAsyncSelect(NETWORK_RECEIVE)。
- 服务器 accept 后向客户端发送“连接成功”提示,客户端在 OnReceive 中显示。
4.3 群聊广播
- 任一客户端 send→服务器 FD_READ→OnReceive→遍历链表 send。
- 所有客户端包括发送者自己都会收到“IP:端口 说:内容”的完整包。
4.4 离线通知
客户端关闭窗口→closesocket→服务器 FD_CLOSE→从链表删除→在线人数-1→UI 实时刷新。
五、扩展指南
5.1 多线程压缩

若客户端规模 >500,可将 WSAAsyncSelect 替换为完成端口,保留现有消息层接口,UI 线程零改动。
5.2 协议升级
目前为裸 TCP 流,可插入 2 字节长度头形成包协议;修改 OnReceive 中缓冲拼装逻辑即可。
5.3 加密通道
在 socket 建立后插入 SSLCTX,send/recv 替换为 SSLwrite/SSL_read,UI 与业务逻辑层无需任何改动。
六、常见问题 FAQ
Q1: 出现 10038 错误?
A: 链表移除与 closesocket 顺序反了,先 erase 再 closesocket 即可。
Q2: 中文显示乱码?
A: 确认双方工程字符集一致,且 AnsiToUnicode/UnicodeToAnsi 使用 CP_ACP 而非固定 936。
Q3: 高并发下 UI 卡顿?
A: WSAAsyncSelect 本质仍是消息泵,建议把业务线程拆出,UI 只负责 PostMessage 刷新。
七、结语

AsyncSocketTCP 用不足千行代码演示了“异步 IO + UI 解耦 + 多客户端管理”的完整闭环:
- 对教学——可直观观察 FDACCEPT、FDREAD、FD_CLOSE 的触发时序;
- 对原型——可快速演化为文件传输、远程控制、即时会议;
- 对工程——只需替换底层 IO 模型即可平移到高并发商业场景。
读懂它,等于拿到了 Windows 网络编程的“最小通用钥匙”。
更多推荐
所有评论(0)