应优先选用CTcpPullServer作为核心对象,因其基于IOCP/EPOLL拉模式适配高并发;CTcpServer仅适用于低负载场景,CTcpPackServer需协议支持固定包头。

HP-Socket 的核心对象怎么选
HP-Socket 不是“拿来就跑”的框架,它把网络模型拆得很开。你得先决定用哪种通信角色:CTcpServer(同步阻塞)、CTcpPullServer(IOCP/EPOLL 拉模式)、CTcpPackServer(自动拆包)——别直接套 CTcpServer 写高并发服务,它在 Linux 下默认用 select,Windows 下用 WSAEventSelect,吞吐上不去,连接一过千就开始丢包或延迟飙升。CTcpPullServer 才是生产环境主力,但注意:它不帮你解析应用层协议,收进来的是一堆裸字节流,得自己做粘包/拆包。
- 用
CTcpPackServer 前确认你的协议有明确包头(比如前 4 字节是包长),否则它会一直等、卡死连接
-
CTcpPullServer 配合 SetFreeBufferPoolSize() 调整内存池大小,小包多时设太小会导致频繁 malloc/free
- Windows 下 IOCP 默认启用,Linux 下必须显式调用
Start() 前设置 SetPollingMode(HP_MODE_EPOLL),否则 fallback 到 select
OnReceive 回调里不能干啥OnReceive 是 HP-Socket 最容易出问题的钩子。它运行在网络线程里,不是你的业务线程——所有耗时操作都得扔出去。常见错误是直接在里面解析 JSON、写数据库、调远程 HTTP,结果整个 IO 线程被堵住,后续连接全卡住。
- 绝对不要在
OnReceive 中调用任何阻塞函数(fread、sleep、同步 socket send/recv)
- 不要 new/delete 大对象,尤其不要 new std::string 或 std::vector —— 内存分配慢,且可能触发锁竞争
- 正确做法是把
pData 和 iLength memcpy 到自定义缓冲区,再 post 到业务线程队列(比如用 boost::lockfree::queue 或 std::queue + mutex)
- 如果只是简单回包(如 echo),可以用
Send(),但注意返回值:返回 SOCKET_ERROR 表示发送缓冲区满,得等 OnSend 回调再重试,不能忽略
如何安全关闭一个 CTcpPullServer
直接调 Stop() 看似干净,实则危险:它会立刻关闭监听 socket,但已建立的连接还在发数据,此时 OnClose 可能还没触发,OnReceive 还在跑,野指针和 use-after-free 就来了。
- 必须先调
DisconnectAll(FALSE),参数 FALSE 表示不立即断开,而是标记为“待关闭”,让正在处理的回调自然结束
- 然后轮询
GetConnectionCount(),直到为 0,再调 Stop()
- 如果用了自定义内存池(
SetFreeBufferPoolSize),记得在析构前调 ClearFreeBufferPool(),否则 valgrind 会报泄漏
- 多线程环境下,确保没有其他线程正拿着
CTcpPullServer* 调 Send(),最好加个原子标志位控制是否允许新请求进入
CTcpPackServer 前确认你的协议有明确包头(比如前 4 字节是包长),否则它会一直等、卡死连接 CTcpPullServer 配合 SetFreeBufferPoolSize() 调整内存池大小,小包多时设太小会导致频繁 malloc/free Start() 前设置 SetPollingMode(HP_MODE_EPOLL),否则 fallback 到 select OnReceive 是 HP-Socket 最容易出问题的钩子。它运行在网络线程里,不是你的业务线程——所有耗时操作都得扔出去。常见错误是直接在里面解析 JSON、写数据库、调远程 HTTP,结果整个 IO 线程被堵住,后续连接全卡住。
- 绝对不要在
OnReceive中调用任何阻塞函数(fread、sleep、同步 socket send/recv) - 不要 new/delete 大对象,尤其不要 new std::string 或 std::vector —— 内存分配慢,且可能触发锁竞争
- 正确做法是把
pData和iLengthmemcpy 到自定义缓冲区,再 post 到业务线程队列(比如用boost::lockfree::queue或std::queue+ mutex) - 如果只是简单回包(如 echo),可以用
Send(),但注意返回值:返回SOCKET_ERROR表示发送缓冲区满,得等OnSend回调再重试,不能忽略
如何安全关闭一个 CTcpPullServer
直接调 Stop() 看似干净,实则危险:它会立刻关闭监听 socket,但已建立的连接还在发数据,此时 OnClose 可能还没触发,OnReceive 还在跑,野指针和 use-after-free 就来了。
- 必须先调
DisconnectAll(FALSE),参数 FALSE 表示不立即断开,而是标记为“待关闭”,让正在处理的回调自然结束
- 然后轮询
GetConnectionCount(),直到为 0,再调 Stop()
- 如果用了自定义内存池(
SetFreeBufferPoolSize),记得在析构前调 ClearFreeBufferPool(),否则 valgrind 会报泄漏
- 多线程环境下,确保没有其他线程正拿着
CTcpPullServer* 调 Send(),最好加个原子标志位控制是否允许新请求进入
DisconnectAll(FALSE),参数 FALSE 表示不立即断开,而是标记为“待关闭”,让正在处理的回调自然结束 GetConnectionCount(),直到为 0,再调 Stop() SetFreeBufferPoolSize),记得在析构前调 ClearFreeBufferPool(),否则 valgrind 会报泄漏 CTcpPullServer* 调 Send(),最好加个原子标志位控制是否允许新请求进入 HP-Socket 的配置项不多,但每个都咬着性能和稳定性。最常被忽略的是日志开关:EnableEventLog() 默认开启,高频连接下打日志会拖慢 20%+,上线前务必关掉;还有 SetKeepAliveTime(),不设的话空闲连接可能被中间设备(NAT、防火墙)静默断开,客户端却不知道,后续发包直接 RST。



















