C# 如何构建MemoryStream数据包并从NetworkStream提取相关数据
方案说明
你当前写的WriteCanvasStrokes和ReadCanvasStrokes核心逻辑已经匹配字符串报文的「1字节操作码 + 4字节内容长度 + N字节内容」结构,完全符合需求,只需要修正两个边缘问题即可稳定运行:
问题1:MemoryStream获取有效字节的错误修正
你现有SendCanvasStrokesToServer方法里调用memoryStream.GetBuffer()是错误的,该方法返回的是内存流预分配的完整底层数组,包含未写入的空白字节,会导致多余无效数据被发送。修改为memoryStream.ToArray()即可获取实际写入的有效字节。
修改后代码:
public void SendCanvasStrokesToServer(MemoryStream memoryStream) { var strokesPacket = new PacketBuilder(); strokesPacket.WriteOpCode(7); // 替换GetBuffer为ToArray获取实际有效字节 strokesPacket.WriteCanvasStrokes(memoryStream.ToArray()); _client.Client.Send(strokesPacket.GetPacketBytes()); }
问题2:接收端读满指定长度的逻辑修正
NetworkStream的Read方法不保证一次就能返回你请求的length长度的字节,尤其是在网络延迟、报文较大的场景下,会出现只读取到部分数据的情况,需要循环读取直到收满指定长度的字节。修改ReadCanvasStrokes方法如下:
public byte[] ReadCanvasStrokes() { var length = ReadInt32(); byte[] strokesBuffer = new byte[length]; int totalRead = 0; while (totalRead < length) { int read = _ns.Read(strokesBuffer, totalRead, length - totalRead); // read返回0说明连接已断开,可根据业务需求调整异常处理逻辑 if (read == 0) { throw new IOException("连接已断开,无法读取完整报文"); } totalRead += read; } return strokesBuffer; }
补充提示:你现有的
ReadMessage方法也存在同样的读取不完整问题,建议用相同的循环读取逻辑修改,避免字符串接收异常。
内容的提问来源于stack exchange,提问作者Kosta
相关产品推荐
相关产品推荐

