本文将展示一个基于C# WinForm的TCP通信实例,包含服务端和客户端的完整实现代码,可用于局域网内的简易消息通信。
一、核心功能
客户端:连接服务器、发送消息、接收消息 服务器:监听端口、管理多客户端、消息广播 技术栈:`TcpClient`/`TcpListener` + `NetworkStream` + 多线程处
二、客户端实现代码解析
using System.Net; using System.Net.Sockets; // …其他命名空间…
namespace WindowsFormsTcpClient { public partial class FormClient : Form { private TcpClient tcpClient = new TcpClient(); private NetworkStream stream;
// 连接服务器按钮 private void buttonConnectServer_Click(object sender, EventArgs e) { try { tcpClient.Connect(IPAddress.Parse("10.92.207.45"), 12138); stream = tcpClient.GetStream(); // 启动接收线程 Task.Run(() => { byte[] data = new byte[1024]; while (true) { int count = stream.Read(data, 0, 1024); if (count == 0) break; // 连接断开 string message = Encoding.Default.GetString(data, 0, count) + "\\r\\n"; this.Invoke(() => { textBoxReceive.Text += message; // 更新UI }); } }); MessageBox.Show("连接成功!"); } catch (Exception ex) { MessageBox.Show($"连接失败:{ex.Message}"); } }
// 发送消息按钮 private void buttonSend_Click(object sender, EventArgs e) { if (stream != null) { String sendString = this.textBoxSend.Text; byte[] data = Encoding.Default.GetBytes(sendString); stream.Write(data, 0, data.Length); } } } }
(客户端部分代码示例)
关键点说明: 1. 使用`Task.Run`创建独立接收线程,避免UI阻塞 2. `stream.Read`会阻塞线程直到收到数据 3. `this.Invoke`确保跨线程安全更新UI 4. 固定IP和端口(12138)需根据实际环境修改
三、服务端实现代码解析
using System.Net; using System.Net.Sockets; // …其他命名空间…
namespace WindowsFormsTcpServer { public partial class FormServer : Form { private TcpListener TcpListener; private Dictionary<String, TcpClient> clients = new Dictionary<string, TcpClient>();
// 启动服务器按钮 private void buttonStartServer_Click(object sender, EventArgs e) { try { TcpListener = new TcpListener(IPAddress.Parse("10.92.207.45"), 12138); TcpListener.Start(); // 监听客户端连接 new Task(() => { while (true) { TcpClient client = TcpListener.AcceptTcpClient(); IPEndPoint endpoint = (IPEndPoint)client.Client.RemoteEndPoint; String ip = endpoint.Address.ToString(); clients.Add(ip, client); // 存储客户端
// 为每个客户端创建接收线程 new Task(() => { NetworkStream stream = client.GetStream(); byte[] data = new byte[1024]; while (true) { int count = stream.Read(data, 0, 1024); String message = Encoding.Default.GetString(data, 0, count) + "\\r\\n"; this.Invoke(() => { textBoxReceive.Text += $"[{ip}] {message}"; // 显示消息来源 }); } }).Start(); } }).Start(); MessageBox.Show("服务器已启动"); } catch (Exception ex) { /* 错误处理 */ } }
// 广播消息按钮 private void buttonSend_Click(object sender, EventArgs e) { foreach (var client in clients.Values) { NetworkStream stream = client.GetStream(); String sendString = this.textBoxSend.Text; byte[] data = Encoding.Default.GetBytes(sendString); stream.Write(data, 0, data.Length); // 向所有客户端发送 } } } }
(服务端部分代码示例)
关键点说明: 1. 使用`Dictionary`存储所有连接的客户端 2. `AcceptTcpClient()`阻塞等待新连接 3. 为每个客户端创建独立接收线程 4. 广播消息遍历所有客户端
四、代码优化建议
1. 连接健壮性改进 // 客户端增加断开检测 if (count == 0) { this.Invoke(() => MessageBox.Show("连接已断开")); break; }
// 服务端增加异常处理 try { int count = stream.Read(data, 0, 1024); // … } catch (IOException) { clients.Remove(ip); // 移除断开连接 break; }
2. 资源释放 // 重写窗体关闭事件 protected override void OnFormClosing(FormClosingEventArgs e) { stream?.Close(); tcpClient?.Close(); base.OnFormClosing(e); }
3. 配置解耦 建议将IP和端口移到配置文件:
//HTIM// <appSettings> <add key="ServerIP" value="10.92.207.45"/> <add key="Port" value="12138"/> </appSettings>
(运行示例)
五、使用注意事项
1. 防火墙设置:需在防火墙开放12138端口 2. IP地址:服务端IP需改为实际本机IP 3. 连接顺序:先启动服务端再启动客户端 4. 广播限制:当前版本未做消息分包处理,长消息可能截断
六、完整项目结构
TCP通信示例 WindowsFormsTcpServer FormServer.cs // 服务端主窗体 app.config // 配置文件 WindowsFormsTcpClient FormClient.cs // 客户端主窗体 ```
通过这个基础框架,您可以扩展实现: 用户认证系统 私聊功能(通过IP识别) 文件传输 心跳检测机制
欢迎在评论区交流实现中遇到的问题或分享改进方案!
评论前必须登录!
注册