简单TCP服务器与客户端实现(C# WinForm)
本文将展示一个基于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) + "
";
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
// 启动服务器按钮
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) + "
";
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//
(运行示例)
五、使用注意事项
1. 防火墙设置:需在防火墙开放12138端口
2. IP地址:服务端IP需改为实际本机IP
3. 连接顺序:先启动服务端再启动客户端
4. 广播限制:当前版本未做消息分包处理,长消息可能截断
六、完整项目结构
TCP通信示例
WindowsFormsTcpServer
FormServer.cs // 服务端主窗体
app.config // 配置文件
WindowsFormsTcpClient
FormClient.cs // 客户端主窗体
```
通过这个基础框架,您可以扩展实现:
用户认证系统
私聊功能(通过IP识别)
文件传输
心跳检测机制
欢迎在评论区交流实现中遇到的问题或分享改进方案!