TCP接收病理分析仪数据后Stream失效,如何重置程序重新接收?
病理分析仪数据接收后无法重新准备接收的问题排查与修复
我正在尝试连接病理分析仪并接收数据,当前代码可以正常运行一次,但完成一次数据传输后就停止工作,每次都需要重启程序才能再次接收。我曾尝试将using (Stream stream = client.GetStream())放入while循环,但分析仪提示LIS is not responding,猜测是设备停止发送数据时stream被using释放,导致后续无法接收。
当前代码
private void ReceiveData(string IP, string PortNo) { var port = Convert.ToInt32(PortNo); IPAddress localAddr = IPAddress.Parse(IP); server = new TcpListener(localAddr, port); byte ACK = 6; byte[] ACK_BUFF = { ACK }; try { server.Start(); var bytes = new byte[1024]; string data = string.Empty; TcpClient client = server.AcceptTcpClient(); using (Stream stream = client.GetStream()) { while (true) { int i; i = stream.Read(bytes, 0, bytes.Length); if (i > 0) { if (chkBidirectional_NI.Checked) stream.Write(ACK_BUFF, 0, ACK_BUFF.Length); string line = Encoding.UTF8.GetString(bytes, 0, i); if (i > 1) { data += line; } if (data.IndexOf("L|1|N") > -1) ReceiveDataSJH(data); } } } } catch (SocketException e) { MessageBox.Show(e.Message); } catch (Exception e) { MessageBox.Show(e.Message); } } private void button1_Click(object sender, EventArgs e) { Thread thrNoti = new Thread(() => ReceiveData(txtIPAddress___.Text, txtPortNo___.Text)); thrNoti.Start(); }
核心错误分析
- 仅接受一次连接:
TcpClient client = server.AcceptTcpClient();放在外层循环外,程序只能处理一个连接,当连接断开后不会再等待新连接。 - 数据拼接逻辑冗余:
if (i > 1)的判断没有意义,会导致长度为1的字节数据被丢弃,可能丢失关键协议标识。 - using语句位置错误:把stream的using放到内部循环会导致每次读取后立即关闭流,直接断开与分析仪的连接,这就是设备提示无响应的原因。
- 无连接断开处理:原循环没有判断连接状态,当设备断开后会一直阻塞在
stream.Read或空转,无法回到等待新连接的状态。
修复后的代码
private void ReceiveData(string IP, string PortNo) { var port = Convert.ToInt32(PortNo); IPAddress localAddr = IPAddress.Parse(IP); server = new TcpListener(localAddr, port); byte ACK = 6; byte[] ACK_BUFF = { ACK }; try { server.Start(); // 持续监听新的连接请求 while (true) { var bytes = new byte[1024]; string data = string.Empty; // 接受新客户端连接,用using自动管理资源 using TcpClient client = server.AcceptTcpClient(); using Stream stream = client.GetStream(); // 处理当前连接的持续数据读取 while (client.Connected) { int readBytes = stream.Read(bytes, 0, bytes.Length); // 读取到0字节表示连接已断开 if (readBytes == 0) { break; } // 发送ACK响应(如果启用双向模式) if (chkBidirectional_NI.Checked) { stream.Write(ACK_BUFF, 0, ACK_BUFF.Length); } // 解析读取到的字节为字符串 string receivedLine = Encoding.UTF8.GetString(bytes, 0, readBytes); data += receivedLine; // 检查是否接收到完整的消息标识 if (data.IndexOf("L|1|N") > -1) { ReceiveDataSJH(data); // 清空缓存,准备接收下一条消息 data = string.Empty; } } // 连接断开后,using会自动释放client和stream资源 } } catch (SocketException e) { MessageBox.Show(e.Message); } catch (Exception e) { MessageBox.Show(e.Message); } finally { // 确保程序退出或异常时停止服务器 server?.Stop(); } } private void button1_Click(object sender, EventArgs e) { Thread thrNoti = new Thread(() => ReceiveData(txtIPAddress___.Text, txtPortNo___.Text)); thrNoti.IsBackground = true; // 设置为后台线程,避免阻塞程序退出 thrNoti.Start(); }
修复说明
- 外层循环监听新连接:确保一个连接断开后,程序立即回到等待状态,接受分析仪的下一次连接请求。
- 自动管理资源:用
using包裹TcpClient和Stream,连接断开时自动释放资源,无需手动清理。 - 完善连接状态判断:当
stream.Read返回0时,判定连接断开,退出当前连接处理循环。 - 修正数据拼接逻辑:移除冗余的
i>1判断,避免丢失短数据。 - 处理后清空缓存:防止旧消息残留干扰下一次数据解析。
- 后台线程设置:避免接收线程阻塞程序正常关闭。
内容的提问来源于stack exchange,提问作者Shaiwal Tripathi
相关产品推荐
相关产品推荐

