开源 C# 快速开发(九)通讯--Tcp客户端

文章的目的为了记录使用C# 开发学习的经历。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。

相关链接:

开源 C# 快速开发(一)基础知识

开源 C# 快速开发(二)基础控件

开源 C# 快速开发(三)复杂控件

开源 C# 快速开发(四)自定义控件--波形图

开源 C# 快速开发(五)自定义控件--仪表盘

开源 C# 快速开发(六)自定义控件--圆环

开源 C# 快速开发(七)通讯--串口

开源 C# 快速开发(八)通讯--Tcp服务器端

开源 C# 快速开发(九)通讯--Tcp客户端

开源 C# 快速开发(十)通讯--http客户端

推荐链接:

开源 C# .net mvc 开发(一)WEB搭建_c#部署web程序-CSDN博客

开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-CSDN博客

开源 C# .net mvc 开发(三)WEB内外网访问-CSDN博客

开源 C# .net mvc 开发(四)工程结构、页面提交以及显示-CSDN博客

开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-CSDN博客

开源 C# .net mvc 开发(六)发送邮件、定时以及CMD编程-CSDN博客

开源 C# .net mvc 开发(七)动态图片、动态表格和json数据生成-CSDN博客

开源 C# .net mvc 开发(八)IIS Express轻量化Web服务器的配置和使用-CSDN博客

开源 C# .net mvc 开发(九)websocket--服务器与客户端的实时通信-CSDN博客

本章节主要内容是:TCP客户端应用程序,基于Windows Forms实现。这个TCP客户端实现了完整的连接管理、数据收发和错误处理机制,是一个功能完备的网络通信客户端。

目录:

1.源码分析

2.所有源码

3.效果演示

一、源码分析

  1. 构造函数和初始化 Form1()

功能:窗体初始化时自动获取并显示本机IP地址。

复制代码
public Form1()
{
    InitializeComponent();
    UpdateLocalIPInfo(); // 初始化时获取本地IP信息
}
  1. 本地IP信息获取 UpdateLocalIPInfo()

技术要点:

使用Dns.GetHostEntry()获取本机所有网络接口的IP地址

过滤出IPv4地址(AddressFamily.InterNetwork)

异常处理确保程序稳定性

复制代码
private void UpdateLocalIPInfo()
{
    try
    {
        string localIP = GetLocalIPAddress(); // 获取本地IPv4地址
        txtClientIP.Text = localIP; // 显示在文本框
    }
    catch (Exception ex)
    {
        txtClientIP.Text = "获取失败";
        AddLog($"获取本地IP失败: {ex.Message}");
    }
}

private string GetLocalIPAddress()
{
    var host = Dns.GetHostEntry(Dns.GetHostName());
    foreach (var ip in host.AddressList)
    {
        if (ip.AddressFamily == AddressFamily.InterNetwork) // 只获取IPv4地址
        {
            return ip.ToString();
        }
    }
    throw new Exception("未找到IPv4地址");
}
  1. 连接服务器 ConnectToServer()

关键特性:

异步连接:使用BeginConnect避免UI线程阻塞

输入验证:严格检查IP和端口格式

UI状态管理:及时更新按钮和状态显示

复制代码
private void ConnectToServer()
{
    try
    {
        // 输入验证
        if (!IPAddress.TryParse(txtServerIP.Text, out IPAddress ipAddress))
        {
            MessageBox.Show("请输入有效的服务器IP地址");
            return;
        }

        if (!int.TryParse(txtServerPort.Text, out int port) || port < 1 || port > 65535)
        {
            MessageBox.Show("请输入有效的端口号(1-65535)");
            return;
        }

        // 异步连接服务器
        tcpClient = new TcpClient();
        tcpClient.BeginConnect(ipAddress, port, new AsyncCallback(ConnectCallback), tcpClient);

        lblStatus.Text = "连接中...";
        btnConnect.Enabled = false; // 防止重复点击
    }
    catch (Exception ex)
    {
        MessageBox.Show($"连接失败: {ex.Message}");
        lblStatus.Text = "连接失败";
        btnConnect.Enabled = true;
    }
}
  1. 连接回调 ConnectCallback(IAsyncResult ar)

重要功能:

连接完成:通过EndConnect完成异步连接操作

本地端口获取:显示客户端使用的本地端口号

自动重连机制:在连接失败时自动尝试重新连接

复制代码
private void ConnectCallback(IAsyncResult ar)
{
    try
    {
        TcpClient client = (TcpClient)ar.AsyncState;
        client.EndConnect(ar); // 完成异步连接

        // 连接成功处理
        isConnected = true;
        clientStream = client.GetStream();
        reconnectAttempts = 0; // 重置重连计数器

        // 获取本地端口号
        string localPort = ((IPEndPoint)client.Client.LocalEndPoint).Port.ToString();

        Invoke(new Action(() =>
        {
            txtClientPort.Text = localPort;
            lblStatus.Text = $"已连接到 {txtServerIP.Text}:{txtServerPort.Text}";
            btnConnect.Enabled = false;
            btnDisconnect.Enabled = true;
            btnSend.Enabled = true;
            AddLog($"连接成功 - 本地端口: {localPort}");
        }));

        // 启动数据接收线程
        receiveThread = new Thread(new ThreadStart(ReceiveData));
        receiveThread.IsBackground = true;
        receiveThread.Start();
    }
    catch (Exception ex)
    {
        Invoke(new Action(() =>
        {
            lblStatus.Text = "连接失败";
            btnConnect.Enabled = true;
            btnDisconnect.Enabled = false;
            AddLog($"连接失败: {ex.Message}");

            // 自动重连逻辑
            if (autoReconnect && reconnectAttempts < MAX_RECONNECT_ATTEMPTS)
            {
                reconnectAttempts++;
                AddLog($"尝试自动重连 ({reconnectAttempts}/{MAX_RECONNECT_ATTEMPTS})...");
                Thread.Sleep(3000); // 等待3秒
                ConnectToServer(); // 重新连接
            }
        }));
    }
}
  1. 数据接收 ReceiveData()

异常处理策略:

IOException:网络连接问题

ObjectDisposedException:资源已被释放

通用异常:其他未知错误

复制代码
private void ReceiveData()
{
    byte[] buffer = new byte[4096]; // 4KB缓冲区
    int bytesRead;

    while (isConnected && tcpClient != null && tcpClient.Connected)
    {
        try
        {
            // 阻塞读取数据
            bytesRead = clientStream.Read(buffer, 0, buffer.Length);
            
            if (bytesRead == 0) // 服务器主动关闭连接
            {
                HandleDisconnection("服务器关闭了连接");
                break;
            }

            string receivedData = Encoding.UTF8.GetString(buffer, 0, bytesRead);

            Invoke(new Action(() =>
            {
                AddLog($"接收: {receivedData}");
            }));
        }
        catch (IOException)
        {
            // 网络连接异常
            HandleDisconnection("连接被中断");
            break;
        }
        catch (ObjectDisposedException)
        {
            // 流已被关闭
            break;
        }
        catch (Exception ex)
        {
            if (isConnected)
            {
                Invoke(new Action(() => AddLog($"接收数据时出错: {ex.Message}")));
            }
            break;
        }
    }
}
  1. 连接断开处理 HandleDisconnection(string reason)

自动重连机制:

最大重试次数:5次(MAX_RECONNECT_ATTEMPTS)

重连间隔:3秒

条件控制:通过autoReconnect复选框启用/禁用

复制代码
private void HandleDisconnection(string reason)
{
    if (!isConnected) return;

    isConnected = false;

    Invoke(new Action(() =>
    {
        lblStatus.Text = "连接已断开";
        btnConnect.Enabled = true;
        btnDisconnect.Enabled = false;
        btnSend.Enabled = false;
        AddLog($"连接断开: {reason}");

        // 自动重连逻辑
        if (autoReconnect && reconnectAttempts < MAX_RECONNECT_ATTEMPTS)
        {
            reconnectAttempts++;
            AddLog($"尝试自动重连 ({reconnectAttempts}/{MAX_RECONNECT_ATTEMPTS})...");
            Thread.Sleep(3000);
            ConnectToServer();
        }
    }));

    // 资源清理
    try
    {
        clientStream?.Close();
        tcpClient?.Close();
    }
    catch { }
}
  1. 主动断开连接 Disconnect()

资源管理:

显式关闭网络流和客户端对象

终止后台接收线程

禁用自动重连功能

复制代码
private void Disconnect()
{
    try
    {
        isConnected = false;
        autoReconnect = false; // 禁用自动重连

        // 终止接收线程
        receiveThread?.Abort();
        receiveThread = null;

        // 关闭网络资源
        clientStream?.Close();
        tcpClient?.Close();

        Invoke(new Action(() =>
        {
            lblStatus.Text = "已断开连接";
            btnConnect.Enabled = true;
            btnDisconnect.Enabled = false;
            btnSend.Enabled = false;
            txtClientPort.Text = ""; // 清空端口显示
            AddLog("主动断开连接");
        }));
    }
    catch (Exception ex)
    {
        Invoke(new Action(() => AddLog($"断开连接时出错: {ex.Message}")));
    }
}
  1. 数据发送 SendData()

发送特性:

连接状态实时验证

UTF-8编码支持中文

发送后自动清空输入框

复制代码
private void SendData()
{
    // 连接状态检查
    if (!isConnected || tcpClient == null || !tcpClient.Connected)
    {
        MessageBox.Show("未连接到服务器");
        return;
    }

    if (string.IsNullOrWhiteSpace(txtSend.Text))
    {
        MessageBox.Show("请输入要发送的数据");
        return;
    }

    try
    {
        byte[] data = Encoding.UTF8.GetBytes(txtSend.Text);
        clientStream.Write(data, 0, data.Length);
        clientStream.Flush(); // 立即发送

        Invoke(new Action(() =>
        {
            AddLog($"发送: {txtSend.Text}");
            txtSend.Clear(); // 清空发送框
        }));
    }
    catch (Exception ex)
    {
        Invoke(new Action(() =>
        {
            AddLog($"发送失败: {ex.Message}");
            HandleDisconnection("发送数据时出错");
        }));
    }
}
  1. 键盘快捷键 txtSend_KeyPress()

用户体验优化:

支持Ctrl+Enter多行发送

支持Enter键快速发送

复制代码
private void txtSend_KeyPress(object sender, KeyPressEventArgs e)
{
    // Ctrl+Enter 发送
    if (e.KeyChar == '\r' && Control.ModifierKeys == Keys.Control)
    {
        e.Handled = true;
        SendData();
    }
    // Enter 发送(单行模式)
    else if (e.KeyChar == '\r' && !txtSend.Multiline)
    {
        e.Handled = true;
        SendData();
    }
}
  1. 日志记录 AddLog(string message)

线程安全:使用Invoke确保跨线程UI操作安全。

复制代码
private void AddLog(string message)
{
    if (txtReceive.InvokeRequired)
    {
        txtReceive.Invoke(new Action<string>(AddLog), message);
    }
    else
    {
        txtReceive.AppendText($"[{DateTime.Now:HH:mm:ss}] {message}\r\n");
        txtReceive.ScrollToCaret(); // 自动滚动到底部
    }
}

二、所有源码

Form1.Designer.cs界面代码

复制代码
using System;
using System.Drawing;
using System.Windows.Forms;

namespace ClientForm
{
    partial class Form1
    {

        /*
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows 窗体设计器生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(800, 450);
            this.Text = "Form1";
        }

        #endregion

        */

        private System.ComponentModel.IContainer components = null;
        private TextBox txtServerIP;
        private TextBox txtServerPort;
        private Button btnConnect;
        private Button btnDisconnect;
        private TextBox txtSend;
        private Button btnSend;
        private TextBox txtReceive;
        private Label lblStatus;
        private Label label1;
        private Label label2;
        private Label label3;
        private Label label4;
        private CheckBox chkAutoReconnect;
        private Button btnClear;
        private TextBox txtClientIP;
        private TextBox txtClientPort;
        private Label label5;
        private Label label6;

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.txtServerIP = new TextBox();
            this.txtServerPort = new TextBox();
            this.btnConnect = new Button();
            this.btnDisconnect = new Button();
            this.txtSend = new TextBox();
            this.btnSend = new Button();
            this.txtReceive = new TextBox();
            this.lblStatus = new Label();
            this.label1 = new Label();
            this.label2 = new Label();
            this.label3 = new Label();
            this.label4 = new Label();
            this.chkAutoReconnect = new CheckBox();
            this.btnClear = new Button();
            this.txtClientIP = new TextBox();
            this.txtClientPort = new TextBox();
            this.label5 = new Label();
            this.label6 = new Label();

            // 窗体设置
            this.Text = "TCP客户端";
            this.Size = new Size(700, 600);
            this.StartPosition = FormStartPosition.CenterScreen;

            // 服务器IP标签和文本框
            this.label1.Location = new Point(20, 20);
            this.label1.Size = new Size(80, 20);
            this.label1.Text = "服务器IP:";
            this.txtServerIP.Location = new Point(100, 20);
            this.txtServerIP.Size = new Size(150, 20);
            this.txtServerIP.Text = "127.0.0.1";

            // 服务器端口标签和文本框
            this.label2.Location = new Point(270, 20);
            this.label2.Size = new Size(80, 20);
            this.label2.Text = "服务器端口:";
            this.txtServerPort.Location = new Point(350, 20);
            this.txtServerPort.Size = new Size(80, 20);
            this.txtServerPort.Text = "8080";

            // 客户端IP标签和文本框(只读,显示本地信息)
            this.label5.Location = new Point(20, 50);
            this.label5.Size = new Size(80, 20);
            this.label5.Text = "本地IP:";
            this.txtClientIP.Location = new Point(100, 50);
            this.txtClientIP.Size = new Size(150, 20);
            this.txtClientIP.ReadOnly = true;

            // 客户端端口标签和文本框(只读,显示本地信息)
            this.label6.Location = new Point(270, 50);
            this.label6.Size = new Size(80, 20);
            this.label6.Text = "本地端口:";
            this.txtClientPort.Location = new Point(350, 50);
            this.txtClientPort.Size = new Size(80, 20);
            this.txtClientPort.ReadOnly = true;

            // 连接按钮
            this.btnConnect.Location = new Point(450, 18);
            this.btnConnect.Size = new Size(80, 25);
            this.btnConnect.Text = "连接";
            this.btnConnect.Click += new EventHandler(this.btnConnect_Click);

            // 断开按钮
            this.btnDisconnect.Location = new Point(540, 18);
            this.btnDisconnect.Size = new Size(80, 25);
            this.btnDisconnect.Text = "断开";
            this.btnDisconnect.Enabled = false;
            this.btnDisconnect.Click += new EventHandler(this.btnDisconnect_Click);

            // 自动重连复选框
            this.chkAutoReconnect.Location = new Point(450, 50);
            this.chkAutoReconnect.Size = new Size(120, 20);
            this.chkAutoReconnect.Text = "自动重连";

            // 状态标签
            this.lblStatus.Location = new Point(20, 85);
            this.lblStatus.Size = new Size(600, 20);
            this.lblStatus.Text = "未连接";

            // 接收数据标签和文本框
            this.label3.Location = new Point(20, 120);
            this.label3.Size = new Size(100, 20);
            this.label3.Text = "接收数据:";
            this.txtReceive.Location = new Point(20, 140);
            this.txtReceive.Multiline = true;
            this.txtReceive.ScrollBars = ScrollBars.Vertical;
            this.txtReceive.Size = new Size(650, 250);
            this.txtReceive.ReadOnly = true;

            // 清空按钮
            this.btnClear.Location = new Point(580, 115);
            this.btnClear.Size = new Size(90, 25);
            this.btnClear.Text = "清空接收区";
            this.btnClear.Click += new EventHandler(this.btnClear_Click);

            // 发送数据标签和文本框
            this.label4.Location = new Point(20, 410);
            this.label4.Size = new Size(100, 20);
            this.label4.Text = "发送数据:";
            this.txtSend.Location = new Point(20, 430);
            this.txtSend.Multiline = true;
            this.txtSend.ScrollBars = ScrollBars.Vertical;
            this.txtSend.Size = new Size(560, 80);

            // 发送按钮
            this.btnSend.Location = new Point(590, 430);
            this.btnSend.Size = new Size(80, 80);
            this.btnSend.Text = "发送";
            this.btnSend.Enabled = false;
            this.btnSend.Click += new EventHandler(this.btnSend_Click);

            // 添加控件到窗体
            this.Controls.AddRange(new Control[] {
            this.txtServerIP, this.txtServerPort, this.btnConnect, this.btnDisconnect,
            this.txtSend, this.btnSend, this.txtReceive, this.lblStatus,
            this.label1, this.label2, this.label3, this.label4,
            this.chkAutoReconnect, this.btnClear, this.txtClientIP,
            this.txtClientPort, this.label5, this.label6
        });



        }
    }
}

Form1.cs代码

复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;



using System.Net;
using System.Net.Sockets;

using System.Threading;
using System.IO;

namespace ClientForm
{
    public partial class Form1 : Form
    {
        /*
        public Form1()
        {
            InitializeComponent();
        }
        */

        private TcpClient tcpClient;
        private NetworkStream clientStream;
        private Thread receiveThread;
        private bool isConnected = false;
        private bool autoReconnect = false;
        private int reconnectAttempts = 0;
        private const int MAX_RECONNECT_ATTEMPTS = 5;

        public Form1()
        {
            InitializeComponent();
            UpdateLocalIPInfo();
        }

        private void UpdateLocalIPInfo()
        {
            try
            {
                // 获取本地IP地址
                string localIP = GetLocalIPAddress();
                txtClientIP.Text = localIP;
            }
            catch (Exception ex)
            {
                txtClientIP.Text = "获取失败";
                AddLog($"获取本地IP失败: {ex.Message}");
            }
        }

        private string GetLocalIPAddress()
        {
            var host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (var ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    return ip.ToString();
                }
            }
            throw new Exception("未找到IPv4地址");
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            ConnectToServer();
        }

        private void ConnectToServer()
        {
            try
            {
                // 验证输入
                if (!IPAddress.TryParse(txtServerIP.Text, out IPAddress ipAddress))
                {
                    MessageBox.Show("请输入有效的服务器IP地址");
                    return;
                }

                if (!int.TryParse(txtServerPort.Text, out int port) || port < 1 || port > 65535)
                {
                    MessageBox.Show("请输入有效的端口号(1-65535)");
                    return;
                }

                // 创建TCP客户端并连接
                tcpClient = new TcpClient();
                tcpClient.BeginConnect(ipAddress, port, new AsyncCallback(ConnectCallback), tcpClient);

                lblStatus.Text = "连接中...";
                btnConnect.Enabled = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"连接失败: {ex.Message}");
                lblStatus.Text = "连接失败";
                btnConnect.Enabled = true;
            }
        }

        private void ConnectCallback(IAsyncResult ar)
        {
            try
            {
                TcpClient client = (TcpClient)ar.AsyncState;
                client.EndConnect(ar);

                // 连接成功
                isConnected = true;
                clientStream = client.GetStream();
                reconnectAttempts = 0;

                // 更新本地端口信息
                string localPort = ((IPEndPoint)client.Client.LocalEndPoint).Port.ToString();

                Invoke(new Action(() =>
                {
                    txtClientPort.Text = localPort;
                    lblStatus.Text = $"已连接到 {txtServerIP.Text}:{txtServerPort.Text}";
                    btnConnect.Enabled = false;
                    btnDisconnect.Enabled = true;
                    btnSend.Enabled = true;
                    AddLog($"连接成功 - 本地端口: {localPort}");
                }));

                // 启动接收线程
                receiveThread = new Thread(new ThreadStart(ReceiveData));
                receiveThread.IsBackground = true;
                receiveThread.Start();
            }
            catch (Exception ex)
            {
                Invoke(new Action(() =>
                {
                    lblStatus.Text = "连接失败";
                    btnConnect.Enabled = true;
                    btnDisconnect.Enabled = false;
                    AddLog($"连接失败: {ex.Message}");

                    // 自动重连逻辑
                    if (autoReconnect && reconnectAttempts < MAX_RECONNECT_ATTEMPTS)
                    {
                        reconnectAttempts++;
                        AddLog($"尝试自动重连 ({reconnectAttempts}/{MAX_RECONNECT_ATTEMPTS})...");
                        Thread.Sleep(3000); // 等待3秒后重连
                        ConnectToServer();
                    }
                }));
            }
        }

        private void ReceiveData()
        {
            byte[] buffer = new byte[4096];
            int bytesRead;

            while (isConnected && tcpClient != null && tcpClient.Connected)
            {
                try
                {
                    bytesRead = clientStream.Read(buffer, 0, buffer.Length);
                    if (bytesRead == 0)
                    {
                        // 连接已关闭
                        HandleDisconnection("服务器关闭了连接");
                        break;
                    }

                    string receivedData = Encoding.UTF8.GetString(buffer, 0, bytesRead);

                    Invoke(new Action(() =>
                    {
                        AddLog($"接收: {receivedData}");
                    }));
                }
                catch (IOException)
                {
                    // 连接被关闭
                    HandleDisconnection("连接被中断");
                    break;
                }
                catch (ObjectDisposedException)
                {
                    // 对象已被释放
                    break;
                }
                catch (Exception ex)
                {
                    if (isConnected)
                    {
                        Invoke(new Action(() => AddLog($"接收数据时出错: {ex.Message}")));
                    }
                    break;
                }
            }
        }

        private void HandleDisconnection(string reason)
        {
            if (!isConnected) return;

            isConnected = false;

            Invoke(new Action(() =>
            {
                lblStatus.Text = "连接已断开";
                btnConnect.Enabled = true;
                btnDisconnect.Enabled = false;
                btnSend.Enabled = false;
                AddLog($"连接断开: {reason}");

                // 自动重连逻辑
                if (autoReconnect && reconnectAttempts < MAX_RECONNECT_ATTEMPTS)
                {
                    reconnectAttempts++;
                    AddLog($"尝试自动重连 ({reconnectAttempts}/{MAX_RECONNECT_ATTEMPTS})...");
                    Thread.Sleep(3000);
                    ConnectToServer();
                }
            }));

            // 清理资源
            try
            {
                clientStream?.Close();
                tcpClient?.Close();
            }
            catch { }
        }

        private void btnDisconnect_Click(object sender, EventArgs e)
        {
            Disconnect();
        }

        private void Disconnect()
        {
            try
            {
                isConnected = false;
                autoReconnect = false;

                // 停止接收线程
                receiveThread?.Abort();
                receiveThread = null;

                // 关闭连接
                clientStream?.Close();
                tcpClient?.Close();

                Invoke(new Action(() =>
                {
                    lblStatus.Text = "已断开连接";
                    btnConnect.Enabled = true;
                    btnDisconnect.Enabled = false;
                    btnSend.Enabled = false;
                    txtClientPort.Text = "";
                    AddLog("主动断开连接");
                }));
            }
            catch (Exception ex)
            {
                Invoke(new Action(() => AddLog($"断开连接时出错: {ex.Message}")));
            }
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            SendData();
        }

        private void SendData()
        {
            if (!isConnected || tcpClient == null || !tcpClient.Connected)
            {
                MessageBox.Show("未连接到服务器");
                return;
            }

            if (string.IsNullOrWhiteSpace(txtSend.Text))
            {
                MessageBox.Show("请输入要发送的数据");
                return;
            }

            try
            {
                byte[] data = Encoding.UTF8.GetBytes(txtSend.Text);
                clientStream.Write(data, 0, data.Length);
                clientStream.Flush();

                Invoke(new Action(() =>
                {
                    AddLog($"发送: {txtSend.Text}");
                    txtSend.Clear();
                }));
            }
            catch (Exception ex)
            {
                Invoke(new Action(() =>
                {
                    AddLog($"发送失败: {ex.Message}");
                    HandleDisconnection("发送数据时出错");
                }));
            }
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            txtReceive.Clear();
        }

        private void chkAutoReconnect_CheckedChanged(object sender, EventArgs e)
        {
            autoReconnect = chkAutoReconnect.Checked;
        }

        private void AddLog(string message)
        {
            if (txtReceive.InvokeRequired)
            {
                txtReceive.Invoke(new Action<string>(AddLog), message);
            }
            else
            {
                txtReceive.AppendText($"[{DateTime.Now:HH:mm:ss}] {message}\r\n");
                txtReceive.ScrollToCaret();
            }
        }

        private void txtSend_KeyPress(object sender, KeyPressEventArgs e)
        {
            // 支持Ctrl+Enter发送
            if (e.KeyChar == '\r' && Control.ModifierKeys == Keys.Control)
            {
                e.Handled = true;
                SendData();
            }
            // 支持Enter发送(需要设置Multiline为true)
            else if (e.KeyChar == '\r' && !txtSend.Multiline)
            {
                e.Handled = true;
                SendData();
            }
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            Disconnect();
            base.OnFormClosing(e);
        }

    }
}

三、效果演示

使用网络调试助手验证,设置好ip和端口号,发送和接收数据,验证通过

相关推荐
青柠编程2 小时前
基于Spring Boot与SSM的中药实验管理系统架构设计
java·开发语言·数据库
远远远远子2 小时前
C++ --1 perparation
开发语言·c++
大飞pkz2 小时前
【设计模式】中介者模式
开发语言·设计模式·c#·中介者模式
tpoog2 小时前
[C++项目框架]gflags和gtest的简单介绍
开发语言·c++
lfq7612042 小时前
C#对称加密(AES)的简单代码
安全·c#·加密·对称加密
电子_咸鱼2 小时前
LeetCode-hot100——验证二叉搜索树
开发语言·数据结构·c++·算法·leetcode·深度优先
NocoBase2 小时前
NocoBase 如何成为 ED 的技术底座,支撑内部系统到商业化产品?
开源·敏捷开发·资讯
ajassi20002 小时前
开源 C# 快速开发(一)基础知识
开源·c#
tryCbest3 小时前
Java实现文件下载
java·开发语言