C# WebSocket 服务端如何向客户端主动回传消息?
问题原因
WebSocket 是基于TCP的上层应用层协议,所有服务端和客户端之间的交互数据都必须按照标准的WebSocket帧格式封装后才能传输。你直接将字符串转为ASCII字节写入流的操作没有遵循帧协议规范,客户端收到非法格式的数据后无法正常解析,会直接判定连接异常主动断开,因此会触发未定义错误。另外使用ASCII编码仅能支持英文字符,若后续传输包含特殊字符或中文内容会出现乱码,建议统一使用UTF8编码。
可行解决方案
- 优先使用.NET官方封装的WebSocket类库
.NET 框架System.Net.WebSockets命名空间已经内置了完整的WebSocket协议实现,无需手动处理帧结构的封装和解析,直接调用内置的发送方法即可,示例代码如下:
// 已完成握手后拿到WebSocket实例对象webSocket byte[] responseBuffer = Encoding.UTF8.GetBytes("Message received by server"); await webSocket.SendAsync( new ArraySegment<byte>(responseBuffer, 0, responseBuffer.Length), WebSocketMessageType.Text, endOfMessage: true, cancellationToken: CancellationToken.None );
- 若场景要求手动实现帧封装逻辑
如果你的项目需要自行实现底层帧处理,需要按照WebSocket协议标准拼接帧结构,长度小于126的文本帧基础拼接逻辑示例如下:
string responseMsg = "Message received by server"; byte[] payload = Encoding.UTF8.GetBytes(responseMsg); // 帧总长度 = 2字节头部 + 负载长度 byte[] frameBuffer = new byte[2 + payload.Length]; // 第一个字节:FIN位为1(代表这是完整消息的最后一帧) + 操作码0x1(代表文本帧),组合为0x81 frameBuffer[0] = 0x81; // 第二个字节:服务端发往客户端的帧不需要掩码,最高位为0,剩余7位填负载长度,小于126时直接写入 frameBuffer[1] = (byte)payload.Length; // 将负载内容复制到帧缓冲区 Buffer.BlockCopy(payload, 0, frameBuffer, 2, payload.Length); // 写入流发送 stream.Write(frameBuffer, 0, frameBuffer.Length);
注意如果发送的内容字节长度大于125,需要额外处理2字节的扩展长度字段;长度大于65535时需要使用8字节的扩展长度位,自行实现需要覆盖所有长度场景的兼容处理,否则仍会出现解析错误,非必要场景不推荐手动实现。
内容的提问来源于stack exchange,提问作者Mihnea Cristian Marin
相关产品推荐
相关产品推荐

