C# WinForm TCP-Socket

一、TCP 基础理论知识点 + 对应代码

1.1 TCP 四大核心特点(背诵知识点)

  • 面向连接:通信前三次握手建立连接

  • 流式无边界传输:数据连续流传输,需要固定缓冲区接收

  • 可靠传输:自带确认重传,无丢包

  • 全双工:两端可同时收发数据

1.2 Socket 核心构造参数(知识点 + 对应代码)

知识点:TCP 套接字固定三参数:IPv4地址族、流式套接字、TCP协议

cs 复制代码
// 对应考点:TCP协议参数固定写法
new Socket(AddressFamily.InterNetwork, 
          SocketType.Stream, 
          ProtocolType.Tcp);

参数释义:

  • AddressFamily.InterNetwork:使用 IPv4 协议

  • SocketType.Stream:TCP 流式传输

  • ProtocolType.Tcp:指定 TCP 通信协议

二、服务端五步法

  1. new Socket() 创建服务端监听对象
  2. Bind() 绑定本机 IP + 端口
  3. Listen(100) 开启端口监听
  4. Accept() 阻塞接收客户端连接
  5. Receive() 循环接收客户端数据

步骤1:创建服务端Socket对象(知识点+代码)

知识点:服务端全局声明Socket对象,用于监听客户端连接

cs 复制代码
// 服务端核心监听对象
Socket server = null;

步骤2:自动获取本机IPv4地址(知识点+代码)

知识点:自动遍历本机所有网卡,筛选IPv4地址,适配不同电脑

cs 复制代码
string ipStr = "";
int port = 63323; // 高位端口,避免冲突

// 获取本机所有网络地址
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress item in host.AddressList)
{
    // 只保留IPv4
    if (item.AddressFamily == AddressFamily.InterNetwork)
    {
        ipStr = item.ToString();
    }
}

步骤3:绑定IP和端口(Bind)(知识点+代码)

知识点:将Socket与本机IP、端口绑定,对外开放服务端口

cs 复制代码
IPAddress address = IPAddress.Parse(ipStr);
IPEndPoint endPoint = new IPEndPoint(address, port);
server.Bind(endPoint); // 绑定端口核心方法

步骤4:开启端口监听(Listen)(知识点+代码)

知识点:Listen(最大挂起连接数),开启端口监听,等待客户端接入

cs 复制代码
server.Listen(100); // 允许最多100个排队连接

步骤5:异步监听多客户端连接(Accept)(知识点+代码)

知识点:双层Task嵌套,外层循环接收新客户端,实现多客户端通信

cs 复制代码
CancellationTokenSource cts;
public void AcceptDataMul()
{
    cts = new CancellationTokenSource();
    Task.Run(() =>
    {
        while (!cts.IsCancellationRequested)
        {
            // 阻塞接收客户端连接
            Socket client = server.Accept();
        }
    }, cts.Token);
}

步骤6:单客户端独立接收数据(知识点+代码)

知识点:每个客户端独立子线程接收数据,互不干扰;修复TCP粘包BUG

cs 复制代码
// 固定缓冲区,解决TCP流式无边界粘包问题
byte[] buffer = new byte[1024 * 10];
int length = client.Receive(buffer);
if (length <= 0) break; // 客户端离线断开

步骤7:跨线程UI更新(必考知识点+代码)

知识点:子线程禁止直接操作UI,必须使用Invoke回调主线程

cs 复制代码
string recStr = Encoding.UTF8.GetString(buffer, 0, length);
Invoke(new Action(() =>
{
    richTextBox1.AppendText(recStr + Environment.NewLine);
}));

步骤8:客户端断开资源释放(知识点+代码)

知识点:捕获异常,主动关闭套接字,避免端口占用、内存泄漏

cs 复制代码
catch (Exception)
{
    client.Close();
    client.Dispose();
    break;
}

服务端关键考点

  • 自动筛选本机 IPv4 地址,排除 IPv6
  • 多客户端原理:双层 Task 外层:循环 Accept 接客户端 内层:每个客户端独立线程收数据
  • 跨线程 UI 报错解决 :子线程更新控件必须用 Invoke
  • TCP 粘包修复 :固定缓冲区 new byte[1024*10]
  • 线程安全CancellationTokenSource 安全终止后台任务

四、客户端四步法

  1. 创建客户端 Socket
  2. 指定服务端 IPEndPoint(IP + 端口)
  3. ConnectAsync 异步连接(不卡死 UI)
  4. Send() 发送数据

步骤1:声明客户端Socket(知识点+代码)

知识点:单客户端通信,仅需一个Socket对象

cs 复制代码
Socket client;

步骤2:创建客户端Socket(知识点+代码)

知识点:客户端参数与服务端一致,保证通信协议匹配

cs 复制代码
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

步骤3:配置服务端终端节点(知识点+代码)

知识点:客户端必须指定服务端精准IP+端口才能连接

cs 复制代码
IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.219.12"), 63323);

步骤4:异步连接服务端(核心考点+代码)

知识点:ConnectAsync异步连接,不阻塞UI主线程,避免界面卡死

cs 复制代码
await client.ConnectAsync(endpoint);

步骤5:连接成功UI状态联动(知识点+代码)

知识点:禁止重复连接,按钮状态互斥,优化交互逻辑

cs 复制代码
label1.Text = "连接成功";
button1.Enabled = false;
button2.Enabled = true;

步骤6:连接失败容错处理(知识点+代码)

知识点:捕获服务端未开启、IP错误、端口错误异常

cs 复制代码
label1.Text = "连接成功";
button1.Enabled = false;
button2.Enabled = true;

五、客户端发送数据 知识点逐段对应

5.1 连接状态校验(防报错知识点+代码)

知识点:发送数据前必须判断Socket非空、处于连接状态

cs 复制代码
if (client == null || !client.Connected)
{
    MessageBox.Show("还没连接到服务器,请先连接服务器");
    return;
}

5.2 空数据校验(规范考点+代码)

知识点:禁止发送空数据,无效通信拦截

cs 复制代码
if (string.IsNullOrEmpty(textBox1.Text))
{
    MessageBox.Show("发送数据不能为空");
    return;
}

5.3 UTF8编码转换(乱码解决考点+代码)

知识点:收发统一UTF8编码,彻底解决中文乱码

cs 复制代码
byte[] data = Encoding.UTF8.GetBytes(textBox1.Text);
client.Send(data);
label1.Text = "发送成功";

5.4 异常完整资源释放(高频考点+代码)

知识点:三段式资源释放:关闭通道→关闭连接→释放资源

cs 复制代码
if (client != null)
{
    if (client.Connected)
        client.Shutdown(SocketShutdown.Both); // 关闭读写通道
    client.Close();   // 关闭连接
    client.Dispose(); // 释放资源
}
// 重置按钮状态
button1.Enabled = true;
button2.Enabled = false;

客户端安全规范

  1. 发送前判空:client!=null && client.Connected
  2. 禁止发送空字符串
  3. 统一 UTF8 编码 防止中文乱码
  4. 异常三步释放资源: ShutdownCloseDispose

五、高频易错点

5.1 线程安全控制(CancellationToken)

知识点:使用取消令牌安全终止异步线程,杜绝后台线程残留

cs 复制代码
CancellationTokenSource cts2 = new CancellationTokenSource();
Task.Run(() => {}, cts2.Token);

5.2 修复TCP原生粘包BUG

知识点:废弃 client.Available 动态缓冲区,使用固定缓冲区循环接收

cs 复制代码
// 正确写法
byte[] buffer = new byte[1024 * 10];
int length = client.Receive(buffer);

// 错误原生写法(已废弃)
// byte[] buffer = new byte[client.Available];
  1. 禁止子线程直接操作 UI,必须 Invoke
  2. TCP 无数据边界,禁用 client.Available
  3. 端口建议高位(>10000)防冲突
  4. 客户端 IP 必须与服务端本机 IPv4 一致
  5. 必须异步连接,同步 Connect 会卡死界面
  6. 通信完毕必须释放资源,否则端口占用、内存泄漏
相关推荐
czhc11400756631 小时前
2026-08-25 博客:现场排查的 8 个坑
c#
周周哈哈哈1 小时前
网络间通信---TCP
网络
程序猿乐锅1 小时前
从 dsh 源码看「一切皆插件」与 Spring IoC
java·网络·数据库·人工智能·后端·spring
艾醒(AiXing-w)1 小时前
LangChain 1.0 入门(五):提示词工程、partial变量、ChatPromptTemplate、Hub模板库
服务器·网络·langchain
Z5998178412 小时前
c#软件开发学习笔记--WPF(控件、样式)
笔记·学习·c#
wno7042 小时前
nginx反向代理设置ssl,支持https
运维·服务器·网络
格林威2 小时前
C#高位深相机图像保存:12位16位图像保存方案,OpenCvSharp和Halcon实现
开发语言·人工智能·数码相机·计算机视觉·c#·视觉检测·工业相机
FreeTinker2 小时前
联想个人云存储:大厂入局NAS赛道,体验如何?
网络
雪隐2 小时前
WPF + MVVM 实战系列03-MVVM 的边界之争,终于有人画了条“差不多”的线
c#