C#使用TcpClient对接TCP服务端设备时无法接收响应消息
问题根因
- 核心原因是
StreamReader.ReadLine()方法要求响应末尾必须包含换行符(\r\n或\n)才会结束读取返回结果,你的TCP设备返回的JSON响应末尾没有换行符,导致方法一直阻塞等待换行符。 - 次要问题:
StreamWriter默认编码为带BOM的UTF-8,部分嵌入式TCP设备无法识别带BOM的UTF-8内容,同时你用WriteLine发送请求时会自动在请求末尾追加换行符,可能不符合设备的请求格式要求。
解决方案
直接换用原始的NetworkStream读取字节流,不要用StreamReader/StreamWriter的行读取逻辑,自行控制读取逻辑即可,修正后可运行的代码示例如下:
using System; using System.Net.Sockets; using System.Text; namespace ModbusJsonTest { class Program { static void Main(string[] args) { const int PORT_NO = 30001; const string SERVER_IP = "192.168.1.1"; // 初始化TcpClient,设置读取超时避免无限阻塞 using TcpClient client = new TcpClient(); client.ReceiveTimeout = 5000; // 超时时间可根据实际场景调整,单位毫秒 client.Connect(SERVER_IP, PORT_NO); NetworkStream stream = client.GetStream(); // 构造请求,转成无BOM的UTF8字节数组 string requestStr = "{\"funcCode\":3,\"slaveId\":31,\"address\":0,\"quantity\":2,\"interval\":0}"; byte[] requestBytes = Encoding.UTF8.GetBytes(requestStr); // 发送请求,不会额外追加换行符 stream.Write(requestBytes, 0, requestBytes.Length); Console.WriteLine("发送请求:" + requestStr); // 读取响应 byte[] buffer = new byte[1024]; // 缓冲区大小可根据实际响应最大长度调整 int bytesRead = stream.Read(buffer, 0, buffer.Length); string response = Encoding.UTF8.GetString(buffer, 0, bytesRead); // 若响应长度超过单缓冲区大小,启用下方循环读取逻辑即可 // while (stream.DataAvailable) // { // bytesRead = stream.Read(buffer, 0, buffer.Length); // response += Encoding.UTF8.GetString(buffer, 0, bytesRead); // } Console.WriteLine("收到响应:" + response); } } }
注意事项
- 如果设备要求请求末尾必须带换行,只需要在构造请求字符串的末尾追加
\n或者\r\n即可。 - 如果设备使用非UTF-8编码(如GB2312),替换代码中的
Encoding.UTF8为对应编码即可。
内容的提问来源于stack exchange,提问作者Tom Boudniatski
相关产品推荐
相关产品推荐

