使用TcpClient读取RFID设备数据时频繁报非连接套接字错误求助
问题修复方案
核心问题
你遇到的错误本质是TCP连接未成功建立时,就尝试对Socket执行读写操作。原代码中调用BeginConnect后仅等待异步句柄,但没有验证连接是否真的成功,一旦连接超时或失败,tcpClient处于未连接状态,后续调用GetStream()、stream.Write()等方法就会触发该错误。
具体修复步骤
1. 替换连接逻辑,确保连接成功后再执行操作
放弃BeginConnect的异步等待方式,改用带超时的同步连接,并在连接后强制检查Connected状态:
// 替换原BeginConnect的代码段 try { // 带超时的同步连接,替代BeginConnect的模拟同步方式 tcpClient.ConnectAsync(DeviceTCPIP, DevicePort).Wait(TimeSpan.FromSeconds(1)); } catch (AggregateException) { // 连接失败/超时,直接跳过本次循环 continue; } // 必须检查连接状态,未连接则跳过后续操作 if (!tcpClient.Connected) { continue; }
2. 优化资源释放与异常处理
- 用
using包裹MemoryStream和NetworkStream,确保资源被正确释放 - 细化Socket异常捕获逻辑,避免不必要的异常抛出
完整修复后的代码
string DeviceTCPIP = "168.34.15.249"; string BackData; string TextMessage; int DevicePort = 5600; Thread threadListen; string ErrorData; void ReadCard() { threadListen = new Thread(() => { while (true) { try { using (TcpClient tcpClient = new()) { try { // 带超时的同步连接 tcpClient.ConnectAsync(DeviceTCPIP, DevicePort).Wait(TimeSpan.FromSeconds(1)); } catch (AggregateException) { Thread.Sleep(100); continue; } // 确认连接成功后再执行后续操作 if (!tcpClient.Connected) { Thread.Sleep(100); continue; } TextMessage = "%DD001**CR"; byte[] bytes = Encoding.ASCII.GetBytes(TextMessage); bytes[bytes.Length - 1] = (byte)13; using (NetworkStream stream = tcpClient.GetStream()) { stream.Write(bytes, 0, bytes.Length); byte[] buffer = new byte[2048]; using (MemoryStream memoryStream = new()) { tcpClient.Client.ReceiveTimeout = 500; int count; do { try { count = stream.Read(buffer, 0, buffer.Length); if (count > 0) { memoryStream.Write(buffer, 0, count); } } catch (IOException ex) { if (!(ex.InnerException is SocketException innerException) || innerException.ErrorCode != 10060) throw; count = 0; } } while (count > 0); BackData = Encoding.ASCII.GetString(memoryStream.ToArray()); if (BackData.Contains("match string")) { Console.WriteLine(BackData); } } } } } catch (Exception ex) { ErrorData = ex.Message.ToString(); } Thread.Sleep(100); } }); threadListen.Start(); }
额外优化建议
- 避免频繁创建
TcpClient:如果设备支持长连接,可保持一个持久连接,而非每次读取都重新连接,减少连接开销和失败概率。 - 改用
async/await替代线程:用异步方法配合Task.Delay代替Thread.Sleep,避免阻塞线程,提升性能。 - 添加连接重试机制:连接失败时可重试1-2次,而非直接跳过。
内容的提问来源于stack exchange,提问作者Hakan Demir
相关产品推荐
相关产品推荐

