使用StreamReader/StreamWriter读取多消息遇问题:客户端仅能读取首条消息
解决StreamReader/StreamWriter多消息接收仅读取第一条的问题
你遇到的问题核心在于客户端每次循环都新建StreamReader实例,多个实例同时操作同一个NetworkStream时,它们的内部缓存会互相干扰,导致后续读取无法正确定位到流的下一个位置,最终只能拿到第一条消息。
先帮你梳理下问题细节:
- 服务端代码是没问题的:你设置了
AutoFlush = true,循环调用WriteLine会把10条"test"消息依次发送到流中,消息本身是正常输出的。 - 客户端的问题出在
WaitMessages方法里:每次进入while循环都创建新的StreamReader,而NetworkStream是连续的字节流,多个StreamReader各自维护缓存,会打乱流的读取位置,自然读不到后续消息。
修正后的客户端代码
public async Task WaitMessages() // 用async Task代替async void,更便于错误处理和调用方控制 { // 只创建一次StreamReader,复用它处理所有消息 using var reader = new StreamReader(LoginChat.Client.TcpClt.GetStream()); while (LoginChat.Client.Connected) { try { var data = await reader.ReadLineAsync(); // 服务端断开连接时,ReadLineAsync会返回null,需要跳出循环 if (data == null) break; MessageBox.Show(data); } catch (Exception ex) { // 这里可以添加异常日志或断开连接的处理逻辑 break; } } }
关键优化点说明
- 复用StreamReader实例:在循环外部创建一次StreamReader,用
using语句确保资源会被正确释放。这样所有读取操作都基于同一个流位置和缓存,能依次读取每条消息。 - 替换async void为async Task:async void仅适合事件处理场景,普通方法用async Task更便于捕获异常、等待执行完成,避免异步操作的潜在问题。
- 处理ReadLineAsync返回null的情况:当服务端主动断开连接时,
ReadLineAsync会返回null,这时候需要跳出循环,避免无限等待无效连接。
另外,服务端代码也可以优化下资源管理,用using语句确保StreamWriter被正确释放:
using var stwWriter = new StreamWriter(client.GetStream()) { AutoFlush = true }; for (int i = 0; i < 10; i++) { stwWriter.WriteLine("test"); }
这样修改后,客户端就能依次接收到服务端发送的10条"test"消息了。
内容的提问来源于stack exchange,提问作者Knautiluz
相关产品推荐
相关产品推荐

