当前位置: 首页 > news >正文

C# TCP 客户端开发笔记(TcpClient)

一、整体功能概述

该代码基于 C# Windows Forms 框架,实现了一个 TCP 客户端程序,用于与 TCP 服务端进行通信,核心功能包括:

  • 连接 / 断开 TCP 服务端

  • 向服务端发送文本数据

  • 接收服务端返回的数据并在界面显示

  • 维护连接状态并提供用户交互反馈

二、核心技术点与类库依赖

1. 关键命名空间

  • System.Net:提供 IP 地址(IPAddress)和网络端点(IPEndPoint)支持

  • System.Net.Sockets:提供 TCP 客户端核心类(TcpClientNetworkStream

  • System.Threading.Tasks:支持异步操作,避免 UI 线程阻塞

  • System.Windows.Forms:提供 Windows 图形界面组件

  • System.Text:提供字符串与字节数组的编码转换

2. 核心组件说明

  • TcpClient:TCP 客户端核心类,负责与服务端建立连接和管理通信

  • IPEndPoint:表示网络端点(IP 地址 + 端口),用于标识客户端和服务端

  • NetworkStream:基于TcpClient的数据流,用于实际的数据传输

  • CancellationTokenSource:用于取消异步任务,特别是在断开连接时

  • Invoke(Action):确保在 UI 线程更新界面控件,避免跨线程操作异常

三、代码结构拆解

1. 全局变量定义

// TCP客户端对象
TcpClient tcpClient = null;
// 服务端网络端点(IP+端口)
IPEndPoint remoteEP = null;
// 任务取消令牌源
CancellationTokenSource cts = null;

2. 构造函数

public Form1()
{InitializeComponent(); // 初始化Windows Forms控件
}
  • 说明:默认构造函数,仅负责初始化界面控件

3. 核心功能方法详解

(1)连接 / 断开按钮点击事件
private async void button1_Click(object sender, EventArgs e)
{try{// 根据按钮文本判断执行连接或断开操作if (button1.Text == "连接"){await ConnectServer(); // 连接服务器AcceptResponse(); // 开始接收服务器响应}else{DisConnectServer(); // 断开连接}}catch (Exception){throw;}
}
  • 逻辑:通过按钮文本状态切换连接状态,使用async/await处理异步操作

(2)连接服务器(ConnectServer
private async Task ConnectServer()
{// 创建本地端点(任意本地IP,系统自动分配端口)IPEndPoint LocalEP = new IPEndPoint(IPAddress.Any, 0);// 定义服务端端点(IP和端口)remoteEP = new IPEndPoint(IPAddress.Parse("172.16.0.28"), 9999);// 初始化TcpClient并绑定本地端点tcpClient = new TcpClient(LocalEP);// 异步连接到服务端await tcpClient.ConnectAsync(IPAddress.Parse("172.16.0.28"), 9999);// 更新按钮文本为"中断",表示已连接button1.Text = "中断";
}
  • 关键点:

    • IPAddress.Any:表示使用本地任意可用 IP 地址

    • 端口 0:表示让系统自动分配可用端口

    • ConnectAsync:异步连接方法,不会阻塞 UI 线程

    • 服务端 IP 和端口硬编码,实际应用中应改为可配置

(3)断开连接(DisConnectServer
private void DisConnectServer()
{// 取消接收响应的任务cts?.Cancel();// 关闭TCP客户端连接tcpClient?.Close();// 更新按钮文本为"连接",表示已断开button1.Text = "连接";
}
  • 资源释放逻辑:先取消任务,再关闭连接,确保资源正确释放

(4)接收服务器响应(AcceptResponse
private void AcceptResponse()
{// 初始化取消令牌源cts = new CancellationTokenSource();// 启动异步任务接收数据Task.Run(async () =>{while (!cts.IsCancellationRequested){try{// 检查客户端是否连接且有可用数据if (!tcpClient.Connected || tcpClient.Available == 0) continue;// 获取网络流NetworkStream stream = tcpClient.GetStream();// 创建缓冲区(大小为可用数据量)byte[] buffer = new byte[tcpClient.Available];// 异步读取数据int count = await stream.ReadAsync(buffer, 0, buffer.Length);if (count == 0) continue;// 线程安全地更新UIInvoke(new Action(() =>{string data = Encoding.UTF8.GetString(buffer);richTextBox1.Text += $"{tcpClient.Client.RemoteEndPoint},{data}" + Environment.NewLine;}));}catch (Exception){throw;}}}, cts.Token);
}
  • 核心逻辑:

    • 使用Task.Run在后台线程接收数据,避免阻塞 UI

    • tcpClient.Available:获取可读取的数据长度

    • ReadAsync:异步读取数据,非阻塞操作

    • Invoke:确保在 UI 线程更新richTextBox1控件

(5)发送数据按钮点击事件(button2_Click
private void button2_Click(object sender, EventArgs e)
{// 检查客户端是否已连接if (tcpClient != null && tcpClient.Connected){// 获取网络流NetworkStream stream = tcpClient.GetStream();// 获取输入框文本并转换为字节数组string msg = textBox1.Text;byte[] buffer = Encoding.UTF8.GetBytes(msg);// 发送数据stream.Write(buffer, 0, buffer.Length);// 在界面显示已发送的数据richTextBox1.Text = $"我是{tcpClient.Client.LocalEndPoint}{msg}" + Environment.NewLine;}else{// 未连接时提示用户MessageBox.Show("先连接服务器,再发送");return;}
}
  • 发送流程:

    1. 检查连接状态

    2. 获取输入文本

    3. 转换为字节数组(UTF8 编码)

    4. 通过网络流发送

    5. 在界面显示发送记录

四、界面控件与交互逻辑

  • button1:连接 / 断开按钮,文本状态表示当前连接状态

  • button2:发送按钮,点击时发送textBox1中的内容

  • textBox1:输入框,用于输入要发送的文本

  • richTextBox1:显示区域,展示发送和接收的消息

五、潜在问题与优化建议

1. 现有代码问题

  • 硬编码服务端地址:服务端 IP 和端口硬编码在代码中,不便于修改

  • 异常处理不完善:多数异常仅抛出未做处理,可能导致程序崩溃

  • 无连接状态实时检测:服务端异常断开时,客户端不能及时感知

  • 发送数据未使用异步stream.Write是同步方法,大数据量时可能卡顿 UI

  • 接收缓冲区设计:依赖tcpClient.Available创建缓冲区,不适合处理大数据

2. 优化建议

  • 将服务端地址改为可配置:添加两个输入框让用户输入 IP 和端口

  • 完善异常处理:

    try
    {await tcpClient.ConnectAsync(ip, port);
    }
    catch (SocketException ex)
    {MessageBox.Show($"连接失败: {ex.Message}");return;
    }
  • 添加连接心跳检测:定期发送心跳包检测连接状态

  • 使用异步发送数据:

    await stream.WriteAsync(buffer, 0, buffer.Length);
  • 使用固定大小缓冲区:

    byte[] buffer = new byte[1024]; // 固定大小缓冲区
    int bytesRead;
    while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
    {// 处理读取的数据
    }
  • 添加 Form 关闭时的资源释放:

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {DisConnectServer();
    }

六、使用与测试说明

  1. 确保服务端已启动并监听指定 IP 和端口

  2. 客户端点击 "连接" 按钮建立连接

  3. 在输入框中输入文本,点击 "发送" 按钮发送数据

  4. 接收的服务端响应会显示在下方文本区域

  5. 点击 "中断" 按钮断开与服务端的连接

该客户端与之前的服务端代码配合使用,可以实现基本的 TCP 通信功能,适合作为 C# 网络编程的入门示例。

http://www.dtcms.com/a/457084.html

相关文章:

  • 网站建设数据库怎么弄个人养老金交15年领多少
  • Linux的Socket编程之TCP
  • ST-Raptor:无需微调,准确率超越 GPT-4o 的半结构化表格问答新范式
  • 深入洞察:华为BLM战略模型和BEM执行模型(图解)
  • wordpress跳转手机站wordpress 短代码 对齐
  • TNNLS-2022《Fast Incomplete Multi-view Clustering with View-independent Anchors》
  • 聊城网站开发培训公司网站可以免费建吗
  • 河南网站设计公司价格青岛企业网站seo技巧
  • 动态DP细谈
  • PHP Exception:深入理解与最佳实践
  • Nginx 反向代理与负载均衡
  • 学校网站建设是什么低价网站建设公司
  • 【HarmonyOS】窗口管理实战指南
  • Java基础加强13-集合框架、Stream流
  • 鸿蒙 hiperf 制作火焰图
  • 随机变量基础教程
  • 鞋子网站建设策划书北京网站设计多少钱
  • 超越传统:精密蚀刻如何实现±1μm的极致公差
  • 鸿蒙NEXT系列之鸿蒙NDK UI 初探
  • gRPC从0到1系列【25】
  • 冠县网站建设电话wordpress优化打开速度插件
  • Redis中string底层实现原理
  • 百度经验官方网站登录入口常州网站建设方案优化
  • 网站改域名如何做百度优化企业网站营销典型案例
  • Java采用easyexcel组件进行excel表格单元格的自动合并
  • 整体设计 逻辑系统程序 之18 Source 容器(Docker)承载 C/P/D 三式的完整设计与双闭环验证 之2
  • 汽车保险网站简历模板大学生
  • 基于pytest的接口测试
  • 阿里巴巴做网站需要多少钱镇江vi设计
  • 嵌入式Linux(以泰山派无 eMMC 版为例,嘉立创给的Linux镜像有问题!)系统报错磁盘不够但我用的是32G不可能不够怎么解决