Skip to content

fix(websocket): 修复WebSocket客户端线程安全与稳定性问题#5

Merged
cyanray merged 4 commits intocyanray:mainfrom
HuoHuas001:main
Feb 15, 2026
Merged

fix(websocket): 修复WebSocket客户端线程安全与稳定性问题#5
cyanray merged 4 commits intocyanray:mainfrom
HuoHuas001:main

Conversation

@HuoHuas001
Copy link
Contributor

Summary

修复了多个线程安全问题、socket 生命周期管理问题和 RFC 6455 合规性问题。

Changes

1. 线程安全 (Thread Safety)

  • status 改为 std::atomic<Status> — 原来 status 在主线程和 RecvLoop 线程之间存在数据竞争(data
    race),属于未定义行为
  • 新增 std::mutex sendMutex 保护发送操作 — 多线程同时调用 SendText/SendBinary 等方法时,底层 send()
    调用可能交错,导致 WebSocket 帧损坏
  • Shutdown()RecvLoop 使用 status.exchange() 原子竞争 — 确保只有一方负责关闭 socket,防止 double-close

2. 线程生命周期管理 (Thread Lifecycle)

  • 线程不再 detach(),改为 join() — 原来 detach 后无法等待线程退出,析构函数中 delete PrivateMembers
    时线程可能仍在访问,导致 use-after-free
  • 析构函数先调用 Shutdown()delete PrivateMembers — 确保线程结束后才释放资源
  • Shutdown() 无论谁关了 socket 都执行 join() — 防止 std::thread 析构时因仍 joinable 而触发 std::terminate

3. 修复 "select error" (Fix select error)

  • select() 返回 -1 时直接 break 退出循环 — 原来只调用 ErrorCallback 但不中断,代码继续执行到
    recv(),对已关闭的 socket 操作导致未定义行为
  • select() 返回 0(超时)时明确 continue — 原来超时后会穿透到帧解析逻辑

4. RFC 6455 合规性

  • mask key 改为每帧随机生成 — 原来使用固定值 {0xd2, 0x28, 0xb6, 0xde},RFC 6455 Section 5.3
    要求客户端每帧使用不可预测的 mask key
  • 修复 payload length 127 的字节序解析 — 原来使用 memcpy 直接拷贝
    uint64_t,在小端架构(x86/ARM)上字节序错误。改为手动按大端(网络字节序)逐字节解析

5. 其他改进

  • Connect() 握手失败或无响应时清理 socket,防止泄漏
  • recv buffer 从 2048 扩大到 4096
  • frame_data.reserve() 从固定 2048 改为 length + 14(按实际需要预分配)
  • TryParseFrame 中增加 mask key 读取前的长度检查,防止越界

HuoHuas001 and others added 4 commits February 3, 2025 02:06
- 修复`select error`报错:`select()`返回错误后不再继续操作已关闭的socket
- `status`改为`std::atomic`,消除主线程与接收线程之间的数据竞争
- 发送操作加`std::mutex`保护,防止多线程发送导致帧交错损坏
- 接收线程不再`detach()`改为`join()`,修复析构时use-after-free
- `Shutdown()`与`RecvLoop`使用原子操作竞争socket关闭权,防止double-close
- 修复payload length 127的字节序解析错误(小端架构)
- mask key改为每帧随机生成,符合RFC 6455规范
- 避免从接收循环线程内部调用Shutdown时出现join自身的情况- 添加线程ID检查以区分当前线程是否为接收线程- 在回调中触发重连时自动分离线程而不是尝试join
- 防止主线程和接收线程之间的潜在死锁情况
@cyanray cyanray merged commit 43e0596 into cyanray:main Feb 15, 2026
@cyanray
Copy link
Owner

cyanray commented Feb 15, 2026

感谢你的 PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments