ClientWebSocket连接失败主因是系统版本不兼容(Win7/8不支持)或证书无效;发送需正确使用ArraySegment并避免缓冲区复用;接收须循环拼接直至EndOfMessage为true;需手动实现心跳与状态检查下的重连。
ClientWebSocket 连接失败的常见报错和原因
直接 new
并调用
却卡住或抛出
,大概率不是代码写错了,而是没处理好底层依赖或网络策略。
Windows 7/8 默认不支持 WebSocket 协议栈,
在这些系统上会静默降级失败(.NET Core 2.1+ 要求 Windows 8.1 或 Server 2012 R2+);另外,如果目标地址是
但证书无效,.NET 不会像浏览器那样弹提示,而是直接抛
带 “The remote certificate is invalid”。
检查运行环境:用
确认系统版本,旧系统必须用第三方库(如
)
调试证书问题:临时加
(仅测试!)
别漏 await:
是异步方法,忘记 await 会导致连接未完成就执行后续逻辑
发送二进制数据时容易踩的坑
的第一个参数是
,不是
或
(.NET 5+ 支持后者,但默认重载仍是前者),传错类型不会编译报错,但可能发空包或触发
。
更隐蔽的问题是缓冲区复用:如果在发送后立刻重置或重用同一段
,而
还没真正发出(尤其在高并发下),就会导致发出去的是脏数据。
发送前确保
的
和
设置正确,不要传整个大数组却只设
避免跨调用复用缓冲区;简单做法是每次发新消息都
,或用
配合
发送字符串建议用
转换,别用
—— 中文环境可能变成 GB2312,服务端解析失败
如何安全地接收并解析连续消息
不保证一次收完一整条消息。WebSocket 协议允许分帧(fragmented frame),尤其当消息较大或网络分片时,你可能会收到多个
,其中只有最后一个的
是
。
C函数速查手册(CHM版)
C函数速查手册(CHM版)
下载
直接把每次
的结果当完整消息处理,会导致 JSON 解析失败、协议头错位等诡异问题。
必须循环调用
,拼接所有
,直到
用
区分
/
/
,收到
必须主动调用
,不能忽略
设置接收超时:在
中设定合理 timeout(比如 30 秒),防止因网络中断卡死在
心跳保活和异常断连后的自动重连
不内置心跳机制。服务器通常 30–60 秒无数据就关连接,客户端若只发不收、也不发 ping,就会被静默踢掉。
单纯捕获
后重连也不够 —— 异常可能发生在 send/receive 过程中,此时 socket 状态已是
或
,再调
会抛
。
用
判断当前状态,只对
或
才发心跳;状态为
/
时必须新建
实例
心跳建议用
发空
帧(如
),比
兼容性更好(某些代理会丢 ping 帧)
重连不要用固定间隔,加 jitter(比如 1~3 秒随机),避免大量客户端同时重连压垮服务器
WebSocket 的“实时”感很依赖连接稳定性,但
本身只是个裸通道,所有保活、重连、粘包处理都得自己补全。最容易被忽略的是:没检查
就盲目调用方法,结果在已关闭的实例上操作,抛出的异常信息还特别不直观。
ClientWebSocket()ConnectAsync()WebSocketExceptionClientWebSocketwss://HttpRequestExceptionEnvironment.OSVersionWebSocket4NetServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;ConnectAsync()SendAsync()ArraySegmentbyte[]MemoryArgumentExceptionbyte[]SendAsync()ArraySegmentOffsetCountCount=1new byte[...]ArrayPool.Shared.Rent() .Return()Encoding.UTF8.GetBytes()Encoding.DefaultReceiveAsync()WebSocketReceiveResultEndOfMessagetrueReceiveAsync()ReceiveAsync()bufferresult.EndOfMessage == trueresult.MessageTypeBinaryTextCloseCloseCloseAsync()CancellationTokenSourceReceiveAsync()ClientWebSocketWebSocketExceptionAbortedCloseReceivedConnectAsync()InvalidOperationExceptionWebSocket.StateOpenConnectingCloseSentAbortedClientWebSocketSendAsync()Text"ping"SendPing()ClientWebSocketWebSocket.State