.NET Framework 4 WinForm Tcp服务端检测客户端断开实现问题
问题核心原因
你当前的代码采用短连接逻辑,服务端收到客户端注册请求并返回响应后,就主动关闭了Socket连接,双方没有保持长连接,自然无法感知客户端后续的离线状态。同时原有服务端代码存在多客户端连接时Socket实例被覆盖的线程安全问题。以下是可直接运行的修改方案:
IpServer 完整修改后代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net; using System.Net.Sockets; using System.Threading; using System.IO; namespace IpServer { public partial class Form1 : Form { public Form1() { InitializeComponent(); } TcpListener tcplist; private void init() { IPAddress ip = IPAddress.Parse("127.0.0.1"); tcplist = new TcpListener(ip,5050); tcplist.Start(); while (true) { // 直接将连接的Socket传入线程,避免类变量被多线程覆盖 Socket clientSocket = tcplist.AcceptSocket(); Thread t = new Thread(() => replay(clientSocket)); t.IsBackground = true; t.Start(); } } private void replay(Socket sc) { NetworkStream ns = new NetworkStream(sc); StreamReader reader = new StreamReader(ns); StreamWriter writer = new StreamWriter(ns) { AutoFlush = true }; string str = ""; string response = ""; try { str = reader.ReadLine(); if (str == "register") { this.Invoke(new Action(() => { MessageBox.Show("客户端注册成功"); })); } response = "registeredSucss,"; writer.WriteLine(response); // 长连接保持循环,持续检测客户端状态 while (sc.Connected) { // 读返回null说明客户端主动断开连接 var heartBeat = reader.ReadLine(); if (heartBeat == null) break; } } catch { // 连接异常断开触发 } finally { // 跨线程调用UI要使用Invoke this.Invoke(new Action(() => { MessageBox.Show("Client Is disconnect"); })); ns.Close(); sc.Close(); } } private void button1_Click(object sender, EventArgs e) { Thread t = new Thread(new ThreadStart(init)); t.IsBackground = true; t.Start(); MessageBox.Show("Server run!!"); button1.Enabled = false; } } }
IpClient 完整修改后代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net; using System.Net.Sockets; using System.IO; namespace IpClient { public partial class Form1 : Form { public Form1() { InitializeComponent(); // 绑定窗体关闭事件,关闭时主动断开连接 this.FormClosing += Form1_FormClosing; } TcpClient tcp; NetworkStream ns; StreamReader reader; StreamWriter writer; string str = ""; private void button1_Click(object sender, EventArgs e) { try { tcp = new TcpClient("127.0.0.1",5050); tcp.ReceiveBufferSize = 25000; tcp.NoDelay = true; ns = tcp.GetStream(); reader = new StreamReader(ns); writer = new StreamWriter(ns) { AutoFlush = true }; writer.WriteLine("register"); str = reader.ReadLine(); string[] strsplit = null; strsplit = str.Split(','); if (strsplit[0] != "registeredSucss") { MessageBox.Show("Not connected"); } else { MessageBox.Show("Your connected"); } // 不再主动关闭连接,保持长连接 } catch { MessageBox.Show("连接服务端失败"); } } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { // 窗体关闭时主动释放连接,触发服务端断开检测 if (tcp != null && tcp.Connected) { tcp.Close(); } } } }
内容的提问来源于stack exchange,提问作者professional
相关产品推荐
相关产品推荐

