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(服务器监听套接字事件)
    ACTURE
    CONTROL(已连接套接字数据事件)

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 启动服务器

  1. 点击“开始服务”→InitNetwork()→WSAStartup→socket→bind→listen→WSAAsyncSelect。
  2. 窗口收到 FDACCEPT→accept 生成新套接字→插入链表→对该套接字再次 WSAAsyncSelect(ACTURECONTROL)。

4.2 客户端接入

  1. 启动客户端→点击“连接”→initnetwork()→socket→connect→WSAAsyncSelect(NETWORK_RECEIVE)。
  2. 服务器 accept 后向客户端发送“连接成功”提示,客户端在 OnReceive 中显示。

4.3 群聊广播

  1. 任一客户端 send→服务器 FD_READ→OnReceive→遍历链表 send。
  2. 所有客户端包括发送者自己都会收到“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 网络编程的“最小通用钥匙”。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐