C#使用StreamReader读取服务端返回字符串时出现截断不完整问题
C# TcpClient响应读取不完整问题修复方案
问题根因
- TCP是面向流的传输协议,本身不存在消息边界,
StreamReader.ReadLine()的返回触发条件为:接收到换行符、输入流关闭、内部缓冲区填满。你遇到的偶发截断是因为单次网络传输仅返回了部分响应数据,未携带完整的换行符,导致ReadLine()提前返回不完整内容,该场景不属于异常,因此不会进入你预设的catch处理逻辑。 - 现有实现的资源管理不规范,每次循环新建/销毁TcpClient连接,频繁的TCP握手挥手容易引发网络波动,也会提升传输异常的概率。
修复方案
前提约定
首先确认服务端的响应规则:如果服务端是短连接模式(返回响应后主动关闭连接),可直接用ReadToEnd()读取完整响应;如果是长连接模式,需确认响应的结束标识(固定换行符/长度前缀),下面的示例基于最常见的「短连接+响应末尾带换行」的场景优化:
using System; using System.IO; using System.Net.Sockets; using System.Text.RegularExpressions; // 正则复用,不要在循环内重复实例化 private static readonly Regex _numRegex = new Regex(@"\d+", RegexOptions.Compiled); // 重试次数限制,避免无限重试 private const int MaxRetryCount = 3; public static void Request1(int start, int end) { for (int i = start; i <= end; i++) { int retryCount = 0; bool success = false; while (retryCount < MaxRetryCount && !success) { try { // using块自动释放资源,无需手动调用Close using TcpClient client = new TcpClient(); client.Connect(server, port); // 设置读写超时,避免无限等待 client.ReceiveTimeout = 5000; client.SendTimeout = 5000; using NetworkStream stream = client.GetStream(); using StreamWriter writer = new StreamWriter(stream); using StreamReader reader = new StreamReader(stream); // 发送请求 string request = i.ToString() + "\n"; writer.WriteLine(request); writer.Flush(); // 读取完整响应,短连接场景下服务端返回后会关连接,ReadToEnd会拿到所有返回内容 string message = reader.ReadToEnd().Trim(); // 校验响应有效性 if (string.IsNullOrEmpty(message)) { throw new InvalidDataException("响应为空"); } Match match = _numRegex.Match(message); if (!match.Success) { throw new InvalidDataException("未匹配到有效数字"); } int result = Convert.ToInt32(match.Value); Console.WriteLine($"Number {i}: {result}"); numList[i] = result; File.AppendAllText("File2.txt", $"Number {i}: {result}\n"); success = true; } catch (Exception ex) { retryCount++; Console.WriteLine($"Number {i} 处理失败,第{retryCount}次重试,异常信息:{ex.Message}"); if (retryCount >= MaxRetryCount) { Console.WriteLine($"Number {i} 已达到最大重试次数,跳过处理"); // 这里可根据业务需求决定是跳过还是抛出异常 } } } } }
额外优化建议
- 如果服务端是长连接模式,不要使用
ReadToEnd(),改为循环读取直到拿到约定的结束标识(比如完整的换行符)。 - 频繁调用
File.AppendAllText性能较低,可改为批量写入或者使用持久化的StreamWriter实例写文件。 - 若并发量较高,建议复用TcpClient连接,避免频繁建立销毁连接的开销。
内容的提问来源于stack exchange,提问作者magrega
相关产品推荐
相关产品推荐

