TcpClient连接办公服务器后发送数据挂起问题排查求助
从你的描述来看,本地测试完全正常,但连接办公服务器时能正常建立/断开连接,发送数据却挂起且服务器无接收记录,旧Delphi程序却能正常工作,这说明问题大概率出在代码的细节处理上,而非网络层面。结合你提供的代码,我梳理了几个关键排查点:
1. 发送数据的循环逻辑存在明显错误
看你SendButton_Click里的循环代码:
for (int cnt = 0; cnt < SingleSendRichTextBox.Lines.Count() - 1; cnt++)
这个条件会导致最后一行文本完全不会被处理!比如如果文本框有3行内容,Lines.Count()是3,循环只会执行cnt=0和cnt=1,索引为2的最后一行直接被跳过。
而你原本的逻辑是要给最后一行加上结束块标识(char)0x1C,现在这个结束符根本没被加到发送数据里。办公服务器很可能在等待这个结束符才会处理报文,导致服务器一直没收到完整数据,不会回复;同时你的客户端在发送后立刻调用ReadAllBytes(),而NetworkStream.Read()是阻塞方法,会一直等待服务器响应,最终表现为程序挂起。
修复建议:
把循环条件改成包含所有行:
for (int cnt = 0; cnt < SingleSendRichTextBox.Lines.Count(); cnt++)
同时修正最后一行的判断逻辑(现在cnt == SingleSendRichTextBox.Lines.Count() - 1就能正确匹配最后一行)。
2. 断开连接的实现不规范
在DisconnectButton_Click中,你直接操作底层套接字:
m_client.Client.Disconnect(false); m_client = new TcpClient();
这种方式没有正确释放NetworkStream和TcpClient的资源,可能导致套接字资源泄漏,后续新建的连接可能存在隐性问题。
修复建议:
改用标准的关闭流程:
case ("DisconnectButton"): if (m_client.Connected) { SingleConnectionRichTextBox.Text += "Connection Terminated\r\n"; ConnectedLightButton.BackColor = Color.Red; try { // 先关闭流,再关闭客户端 m_client.GetStream().Close(); } catch { } m_client.Close(); m_client = new TcpClient(); } break;
3. 阻塞读取没有超时机制
ReadAllBytes()中的stm.Read()是阻塞调用,如果服务器因为数据不完整等原因不回复,客户端会一直卡在这个方法上,完全失去响应。
修复建议:
给NetworkStream设置读取超时,比如5秒,这样即使服务器没回复,也会抛出超时异常,方便你定位问题:
public void ReadAllBytes() { try { Byte[] readdata = new Byte[256]; String responseData = String.Empty; NetworkStream stm = m_client.GetStream(); stm.ReadTimeout = 5000; // 设置5秒超时 Int32 bytes = stm.Read(readdata, 0, readdata.Length); responseData = Encoding.ASCII.GetString(readdata, 0, bytes); SingleReplyRichTextBox.Text += responseData + "\r\n"; } catch (Exception err) { MessageBox.Show(err.ToString()); } }
4. 验证发送数据的完整性
建议在WriteBytes方法中添加日志,输出发送的字节数和十六进制格式的数据,和旧Delphi程序发送的内容做对比,确认数据格式(包括起始符、结束符、换行符)完全一致:
public void WriteBytes(Byte[] data) { try { if ((m_client.Connected)&&(data.Length > 0)) { NetworkStream stm = m_client.GetStream(); stm.Write(data, 0, data.Length); stm.Flush(); // 添加日志,查看发送的字节详情 SingleConnectionRichTextBox.Text += $"Sent {data.Length} bytes: {BitConverter.ToString(data)}\r\n"; } else { MessageBox.Show("Either we are not connected, or there is no data to send!!"); } } catch (Exception err) { MessageBox.Show(err.ToString()); } }
总结
最可能导致你当前问题的核心原因是发送数据时遗漏了最后一行,没有加上服务器期望的结束符,导致服务器不处理也不回复,客户端阻塞在读取操作上。先修复循环逻辑的问题,再配合超时和日志排查,应该能解决问题。
内容的提问来源于stack exchange,提问作者D. Haskins

