.Net TCP/IP数据接收:如何判断客户端停止发送并断开连接
如何判断TCP客户端已停止发送并断开连接
嘿,我看你的代码已经能正常接收客户端数据了,现在就差判断客户端断开的逻辑对吧?其实在TCP通信里,判断客户端断开有两个核心判断点:
- 当
NetworkStream.Read()返回0时,说明客户端主动关闭了连接,这是TCP协议定义的正常断开信号 - 如果客户端异常断开(比如突然断电、网络中断),
Read()方法会抛出IOException,我们需要捕获这个异常来处理异常断开的情况
你的现有代码里ThreadProc方法的while(true)循环没有退出条件,也没处理读取异常,这就是没法判断断开的原因。下面是修改后的完整代码,我加上了断开判断、异常处理和资源清理的逻辑:
static void Main(string[] args) { TcpListener listener = new TcpListener(IPAddress.Any, 34400); TcpClient client; listener.Start(); while (true) // 可以在这里加一个退出标志,比如监听控制台输入来终止程序 { client = listener.AcceptTcpClient(); ThreadPool.QueueUserWorkItem(ThreadProc, client); } } private static void ThreadProc(object state) { string imei = string.Empty; var client = (TcpClient)state; NetworkStream nwStream = client.GetStream(); byte[] buffer = new byte[client.ReceiveBufferSize]; try { // 核心修改:通过bytesRead的返回值判断连接状态 int bytesRead; while ((bytesRead = nwStream.Read(buffer, 0, client.ReceiveBufferSize)) > 0) { string dataReceived = Encoding.ASCII.GetString(buffer, 0, bytesRead); if (imei == string.Empty) { imei = dataReceived; Console.WriteLine("IMEI received : " + dataReceived); Byte[] b = { 0x01 }; nwStream.Write(b, 0, 1); } else { int dataNumber = Convert.ToInt32(buffer.Skip(9).Take(1).ToList()[0]); var result = 0; while (dataNumber > 0) { var parser = new TeltonikaDevicesParser(false); result = parser.Decode(new List<byte>(buffer), imei); dataNumber--; } nwStream.Write( result > 0 ? new byte[] { 0x00, 0x00, 0x00, 0x01 } : new byte[] { 0x00, 0x00, 0x00, 0x00 }, 0, 4); } } // 走到这里说明bytesRead返回0,客户端正常断开 Console.WriteLine($"客户端 {client.Client.RemoteEndPoint} 已正常断开连接"); } catch (IOException ex) { // 捕获IO异常,通常对应客户端异常断开场景 Console.WriteLine($"客户端 {client.Client.RemoteEndPoint} 异常断开:{ex.Message}"); } catch (ObjectDisposedException) { // 补充捕获资源已释放的异常,避免程序崩溃 Console.WriteLine($"客户端 {client.Client.RemoteEndPoint} 连接资源已被释放"); } finally { // 不管是正常断开还是异常,都要确保释放资源 nwStream?.Close(); client?.Close(); Console.WriteLine($"已释放客户端 {client.Client.RemoteEndPoint} 的连接资源"); } }
另外补充几个实用细节:
- 如果你的业务有自定义的“结束发送”规则(比如客户端发送特定的结束符),还可以在读取到数据后判断是否是结束符,主动退出循环,这属于应用层的断开判断,可以和TCP层的断开逻辑结合使用
finally块里的资源释放非常重要,能避免长时间运行后出现资源泄漏问题- 你可以在
Main方法的while(true)循环里添加退出逻辑,比如监听Console.ReadLine()来终止整个服务
内容的提问来源于stack exchange,提问作者Baouche Iqbal
相关产品推荐
相关产品推荐

