C# Socket 讲解 + WinForm 客户端 / 服务端完整代码
·
一、C# Socket 核心讲解
1. 什么是 Socket?
Socket(套接字)是网络通信的基石,是两台设备(客户端 / 服务端)之间建立网络连接、收发数据的通信端点。简单理解:Socket 就像网络电话,服务端是「座机」,提前开机等待呼叫;客户端是「手机」,主动拨号连接,连接成功后双方可以互相通话(收发数据)。
2. Socket 核心工作流程
- 服务端:创建 Socket → 绑定 IP + 端口 → 监听连接 → 接受客户端连接 → 收发数据 → 关闭连接
- 客户端:创建 Socket → 主动连接服务端 → 收发数据 → 关闭连接
3. C# 中 Socket 常用类 / 方法
- Socket 类:核心类,负责创建套接字、连接、收发数据
- IPAddress:解析 IP 地址
- IPEndPoint:封装
IP+端口,作为通信端点 - Listen():服务端开启监听
- Accept():服务端接受客户端连接
- Connect():客户端主动连接服务端
- Send()/Receive():收发字节数据(网络传输统一用字节)
- 异步方法:
AcceptAsync()/ReceiveAsync()(WinForm 必须用异步,避免界面卡死)
4. 关键注意点
- WinForm 是界面线程,Socket 网络操作必须用异步,否则界面会卡死
- 数据传输:字符串需要转
byte[]发送,接收后转回字符串 - 必须处理异常(断网、连接失败、客户端退出等)
二、WinForm Socket 服务端
1. 界面设计(拖控件)
新建 WinForm 项目,拖入以下控件:
TextBox(命名:txtIP):默认填127.0.0.1TextBox(命名:txtPort):默认填8888Button(命名:btnStart):文本「启动服务」Button(命名:btnStop):文本「停止服务」RichTextBox(命名:rtbMsg):显示日志TextBox(命名:txtSendMsg):发送消息输入框Button(命名:btnSend):文本「发送消息」
2. 服务端代码
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SocketServer_WinForm
{
public partial class ServerForm : Form
{
// 服务端Socket
private Socket serverSocket;
// 客户端连接Socket(单客户端,如需多客户端需用列表管理)
private Socket clientSocket;
public ServerForm()
{
InitializeComponent();
// 初始化默认值
txtIP.Text = "127.0.0.1";
txtPort.Text = "8888";
// 关闭时释放资源
FormClosing += ServerForm_FormClosing;
}
// 启动服务
private async void btnStart_Click(object sender, EventArgs e)
{
try
{
btnStart.Enabled = false;
btnStop.Enabled = true;
// 1. 创建Socket(IPv4,流式连接,TCP协议)
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 2. 绑定IP和端口
IPAddress ip = IPAddress.Parse(txtIP.Text.Trim());
IPEndPoint point = new IPEndPoint(ip, int.Parse(txtPort.Text.Trim()));
serverSocket.Bind(point);
// 3. 开启监听(最多挂起10个连接)
serverSocket.Listen(10);
AddMsg("服务启动成功,等待客户端连接...");
// 4. 异步等待客户端连接(不卡死界面)
await AcceptClientAsync();
}
catch (Exception ex)
{
AddMsg($"启动失败:{ex.Message}");
btnStart.Enabled = true;
btnStop.Enabled = false;
}
}
// 异步接受客户端连接
private async Task AcceptClientAsync()
{
try
{
// 等待客户端连接
clientSocket = await serverSocket.AcceptAsync();
AddMsg($"客户端【{clientSocket.RemoteEndPoint}】已连接!");
// 连接成功后,异步接收客户端消息
await ReceiveMsgAsync();
}
catch (Exception ex)
{
AddMsg($"客户端连接异常:{ex.Message}");
}
}
// 异步接收客户端消息
private async Task ReceiveMsgAsync()
{
try
{
byte[] buffer = new byte[1024 * 4]; // 4K缓冲区
while (true)
{
// 接收数据
int length = await clientSocket.ReceiveAsync(new ArraySegment<byte>(buffer), SocketFlags.None);
if (length == 0) // 客户端断开
{
AddMsg("客户端已断开连接");
break;
}
// 字节转字符串
string msg = Encoding.UTF8.GetString(buffer, 0, length);
AddMsg($"客户端:{msg}");
}
}
catch (Exception ex)
{
AddMsg($"接收消息异常:{ex.Message}");
}
}
// 发送消息给客户端
private void btnSend_Click(object sender, EventArgs e)
{
if (clientSocket == null || !clientSocket.Connected)
{
MessageBox.Show("无客户端连接!");
return;
}
if (string.IsNullOrWhiteSpace(txtSendMsg.Text))
{
MessageBox.Show("请输入消息!");
return;
}
try
{
byte[] buffer = Encoding.UTF8.GetBytes(txtSendMsg.Text.Trim());
clientSocket.Send(buffer);
AddMsg($"服务端:{txtSendMsg.Text.Trim()}");
txtSendMsg.Clear();
}
catch (Exception ex)
{
AddMsg($"发送失败:{ex.Message}");
}
}
// 停止服务
private void btnStop_Click(object sender, EventArgs e)
{
CloseSocket();
btnStart.Enabled = true;
btnStop.Enabled = false;
AddMsg("服务已停止");
}
// 关闭Socket
private void CloseSocket()
{
clientSocket?.Close();
serverSocket?.Close();
clientSocket = null;
serverSocket = null;
}
// 窗体关闭时释放资源
private void ServerForm_FormClosing(object sender, FormClosingEventArgs e)
{
CloseSocket();
}
// 安全添加日志到界面
private void AddMsg(string msg)
{
if (rtbMsg.InvokeRequired)
{
rtbMsg.Invoke(new Action(() => AddMsg(msg)));
}
else
{
rtbMsg.AppendText($"{DateTime.Now:HH:mm:ss} {msg}\r\n");
rtbMsg.ScrollToCaret(); // 自动滚动到底部
}
}
}
}
三、WinForm Socket 客户端(完整可运行)
1. 界面设计(和服务端一致)
新建 WinForm 项目,拖入相同控件:
TextBox(txtIP):127.0.0.1TextBox(txtPort):8888Button(btnConnect):「连接服务」Button(btnDisconnect):「断开连接」RichTextBox(rtbMsg):日志TextBox(txtSendMsg):发送框Button(btnSend):发送
2. 客户端代码
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SocketClient_WinForm
{
public partial class ClientForm : Form
{
// 客户端Socket
private Socket clientSocket;
public ClientForm()
{
InitializeComponent();
txtIP.Text = "127.0.0.1";
txtPort.Text = "8888";
FormClosing += ClientForm_FormClosing;
}
// 连接服务端
private async void btnConnect_Click(object sender, EventArgs e)
{
try
{
btnConnect.Enabled = false;
btnDisconnect.Enabled = true;
// 1. 创建Socket
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 2. 异步连接服务端
IPAddress ip = IPAddress.Parse(txtIP.Text.Trim());
IPEndPoint point = new IPEndPoint(ip, int.Parse(txtPort.Text.Trim()));
await clientSocket.ConnectAsync(point);
AddMsg("成功连接到服务端!");
// 连接后异步接收服务端消息
await ReceiveMsgAsync();
}
catch (Exception ex)
{
AddMsg($"连接失败:{ex.Message}");
btnConnect.Enabled = true;
btnDisconnect.Enabled = false;
}
}
// 异步接收服务端消息
private async Task ReceiveMsgAsync()
{
try
{
byte[] buffer = new byte[1024 * 4];
while (true)
{
int length = await clientSocket.ReceiveAsync(new ArraySegment<byte>(buffer), SocketFlags.None);
if (length == 0)
{
AddMsg("服务端已断开");
break;
}
string msg = Encoding.UTF8.GetString(buffer, 0, length);
AddMsg($"服务端:{msg}");
}
}
catch (Exception ex)
{
AddMsg($"接收消息异常:{ex.Message}");
}
}
// 发送消息给服务端
private void btnSend_Click(object sender, EventArgs e)
{
if (clientSocket == null || !clientSocket.Connected)
{
MessageBox.Show("未连接服务端!");
return;
}
if (string.IsNullOrWhiteSpace(txtSendMsg.Text))
{
MessageBox.Show("请输入消息!");
return;
}
try
{
byte[] buffer = Encoding.UTF8.GetBytes(txtSendMsg.Text.Trim());
clientSocket.Send(buffer);
AddMsg($"客户端:{txtSendMsg.Text.Trim()}");
txtSendMsg.Clear();
}
catch (Exception ex)
{
AddMsg($"发送失败:{ex.Message}");
}
}
// 断开连接
private void btnDisconnect_Click(object sender, EventArgs e)
{
CloseSocket();
btnConnect.Enabled = true;
btnDisconnect.Enabled = false;
AddMsg("已断开连接");
}
// 关闭Socket
private void CloseSocket()
{
clientSocket?.Close();
clientSocket = null;
}
// 窗体关闭释放资源
private void ClientForm_FormClosing(object sender, FormClosingEventArgs e)
{
CloseSocket();
}
// 安全添加日志
private void AddMsg(string msg)
{
if (rtbMsg.InvokeRequired)
{
rtbMsg.Invoke(new Action(() => AddMsg(msg)));
}
else
{
rtbMsg.AppendText($"{DateTime.Now:HH:mm:ss} {msg}\r\n");
rtbMsg.ScrollToCaret();
}
}
}
}
四、运行使用步骤
- 先启动服务端:运行服务端项目 → 点击【启动服务】
- 再启动客户端:运行客户端项目 → 点击【连接服务】
- 互发消息:双方输入文字 → 点击【发送消息】,即可实时通信
- 关闭:先停止服务 / 断开连接,再关闭窗体
五、核心知识点总结
- TCP 协议:两份代码都用的可靠 TCP 连接(保证数据不丢失、不乱序)
- 异步 async/await:WinForm 必须用,解决界面卡死问题
- 字节编码:网络传输必须用
byte[],用UTF8编码保证中文不乱码 - 线程安全:跨线程更新界面用
Invoke,否则会报错 - 资源释放:关闭前必须
Close()Socket,避免端口占用
总结
- Socket 是网络通信端点,服务端监听、客户端主动连接,TCP 是最常用的可靠通信方式
- 两份代码是标准单客户端单服务端模板,直接复制到 WinForm 即可运行
- 核心:异步操作 + 字节编码 + 线程安全 + 资源释放
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)