C#实现TCP客户端和服务器的基本功能

 更新时间:2024年12月10日 08:53:59   作者:数据的世界01  
本文将介绍如何使用C#实现TCP客户端和服务器的基本功能,客户端与服务器可以相互发送消息,文章通过代码讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下

效果展示

服务器端实现

首先,我们实现TCP服务器。以下是服务器端所需的类和代码:

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
 
namespace TCPIP_Test {
    public class TcpIp_Server {
        Socket serverSocket; // 服务器端Socket,用于服务器与客户端的通信
        Socket clientSocket; // 客户端Socket,用于与客户端建立连接
        TcpListener tcpListener; // 负责监听客户端的连接请求
        Thread tcpListenerThread; // 监听连接请求的线程
        Dictionary<string, Socket> dicClientSockets = new Dictionary<string, Socket>(); // 存储客户端Socket的集合,以客户端的IP/端口作为键
        Dictionary<string, Thread> dicReceiveMsg = new Dictionary<string, Thread>(); // 存储每个客户端接收消息的线程集合
 
        string _IP; // 服务器的IP地址
        int _Port; // 服务器的端口
        IPAddress _ipAddress; // 服务器的IPAddress对象
        EndPoint _endPoint; // 服务器的端点,包括IP地址和端口
        bool linked = false; // 标识服务器是否已开始监听客户端连接
        bool unlinked = false; // 标识服务器是否已关闭连接
 
        // 构造函数,初始化服务器的IP和端口
        public TcpIp_Server(string ip, int port) {
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 初始化Socket对象,使用TCP协议
            _IP = ip;
            _Port = port;
            _ipAddress = IPAddress.Parse(ip); // 将IP地址字符串转换为IPAddress对象
            _endPoint = new IPEndPoint(_ipAddress, port); // 构造服务器端点
        }
 
        // 判断服务器是否已绑定到指定的端口
        private bool _IsBound;
        public bool IsBound {
            get { return _IsBound = serverSocket.IsBound; }
        }
 
        // 判断服务器Socket是否已连接
        private bool _Connected;
        public bool Connected {
            get { return _Connected = serverSocket.Connected; }
        }
 
        // 绑定服务器并开始监听客户端连接
        public bool Bind(ref string msg) {
            try {
                if (!linked) {
                    tcpListener = new TcpListener(_ipAddress, _Port); // 创建TcpListener对象,绑定IP和端口
                    tcpListener.Start(); // 启动监听
                    linked = true; // 标记已开始监听
                    ThreadStart threadStart = new ThreadStart(ListenConnectRequest); // 创建一个委托,执行监听连接请求的方法
                    tcpListenerThread = new Thread(threadStart); // 创建一个新线程来监听客户端请求
                    tcpListenerThread.IsBackground = true; // 设置为后台线程
                    tcpListenerThread.Start(); // 启动监听线程
                    msg = $"[Info] 服务器{tcpListener.LocalEndpoint.ToString()}监听成功!"; // 返回监听成功的消息
                    return true;
                }
                else {
                    msg = $"[Info] 已监听"; // 如果已经开始监听,则返回已监听消息
                    return true;
                }
            }
            catch (Exception ex) {
                msg = $"[Err] 连接失败!信息={ex}"; // 如果发生异常,返回错误信息
                return false;
            }
        }
 
        // 断开与指定客户端的连接
        public bool DisConnectClient(string client, ref string msg) {
            try {
                if (dicClientSockets.ContainsKey(client)) {
                    dicClientSockets[client].Close(); // 关闭与客户端的连接
                    msg = $"[Info] 断开客户端{client}连接"; // 返回断开成功的消息
                    return true;
                }
                else {
                    msg = $"[Info] 客户端{client}已断开"; // 如果客户端已断开,返回已断开消息
                    return true;
                }
            }
            catch (Exception ex) {
                msg = $"[Err] 断开失败!信息={ex}"; // 如果发生异常,返回错误信息
                return false;
            }
        }
 
        // 关闭服务器监听并断开所有客户端连接
        public bool ShutDown(string[] clientList, ref string msg) {
            try {
                if (linked) {
                    linked = false; // 标记服务器停止监听
                    tcpListener.Stop(); // 停止TcpListener监听
                    for (int i = 0; i < clientList.Length; i++) {
                        dicClientSockets[clientList[i]].Close(); // 关闭每个客户端的连接
                    }
                    msg = $"[Info] 服务器监听断开"; // 返回关闭监听的消息
                    return true;
                }
                else {
                    unlinked = true; // 标记已断开
                    msg = $"[Info] 已断开"; // 返回已断开消息
                    return true;
                }
            }
            catch (Exception ex) {
                tcpListener.Stop(); // 停止TcpListener
                unlinked = true; // 标记已断开
                msg = $"[Info] 已断开!!!"; // 返回关闭连接的消息
                return false;
            }
        }
 
        // 向指定客户端发送数据
        public bool SendToClient(string client, string cmd, ref string msg) {
            try {
                if (!string.IsNullOrEmpty(cmd)) {
                    dicClientSockets[client].Send(Encoding.UTF8.GetBytes(cmd)); // 将命令数据发送给客户端
                    msg = $"[Info] 发送{client}信息={cmd}"; // 返回发送成功的消息
                    return true;
                }
                else
                    return false; // 如果命令为空,返回发送失败
            }
            catch (Exception ex) {
                msg = $"[Err] 发送信息失败!信息={ex}"; // 如果发送失败,返回错误信息
                return false;
            }
        }
 
        // 监听客户端的连接请求
        private void ListenConnectRequest() {
            while (linked) {
                try {
                    Socket clientSocket = tcpListener.AcceptSocket(); // 等待并接受客户端连接
                    ParameterizedThreadStart parameterizedThreadStart = new ParameterizedThreadStart(ReceiveData); // 创建接收数据的线程委托
                    Thread receiveMsgThread = new Thread(parameterizedThreadStart); // 创建一个线程来接收客户端数据
                    receiveMsgThread.IsBackground = true; // 设置为后台线程
                    receiveMsgThread.Start(clientSocket); // 启动线程并传入客户端Socket
                    dicClientSockets.Add(clientSocket.RemoteEndPoint.ToString(), clientSocket); // 将客户端Socket加入字典
                    dicReceiveMsg.Add(clientSocket.RemoteEndPoint.ToString(), receiveMsgThread); // 将接收消息线程加入字典
                    Form_Server._AddListEvent(clientSocket.RemoteEndPoint.ToString()); // 更新UI列表,显示已连接的客户端
                }
                catch (Exception ex) {
                    Form_Server._ShowServerLogEvent($"[Err] 监听失败!信息={ex}"); // 监听失败时显示错误日志
                }
            }
        }
 
        // 接收客户端发送的数据
        public void ReceiveData(Object obj) {
            Socket clientSocket = (Socket)obj; // 将传入的参数转换为Socket
            string str = clientSocket.RemoteEndPoint.ToString(); // 获取客户端的远程端点(IP+端口)
            while (true) {
                try {
                    byte[] buffer = new byte[1024 * 1024]; // 创建缓存区,大小为1MB
                    int length = clientSocket.Receive(buffer); // 接收客户端数据
                    string message = Encoding.UTF8.GetString(buffer, 0, length); // 将字节数组转换为字符串
                    if (length != 0) {
                        Form_Server._ShowServerLogEvent($"[Info] 接收客户端{clientSocket.RemoteEndPoint}信息={message}"); // 显示接收到的消息
                    }
                }
                catch (Exception) {
                    Form_Server._RemoveListEvent(str); // 从UI列表中移除已断开的客户端
                    dicClientSockets.Remove(str); // 从客户端字典中移除该客户端的Socket
                    dicReceiveMsg.Remove(str); // 从接收消息线程字典中移除该客户端的线程
                    break; // 退出接收数据的循环
                }
            }
        }
    }
}

代码解析:

服务器初始化: 在构造函数中,初始化了服务器的Socket、监听端口和IP地址。
绑定与监听: Bind() 方法会启动一个监听线程,等待客户端连接请求。
客户端连接管理: 客户端连接通过 ListenConnectRequest() 方法处理。每当有客户端连接时,创建一个新的线程来接收客户端数据。
发送与接收数据: SendToClient() 方法用于发送数据到指定客户端,而 ReceiveData() 方法则接收客户端发送的数据。
断开与关闭: DisConnectClient() 和 ShutDown() 方法分别用于断开客户端连接和关闭服务器监听。

接下来是服务器界面的代码:

using System;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
 
namespace TCPIP_Test {
    // 委托用于更新服务器日志
    public delegate void ShowServerLogDelegate(string message);
    // 委托用于向客户端列表中添加客户端
    public delegate void AddListDelegate(string value);
    // 委托用于从客户端列表中移除客户端
    public delegate void RemoveListDelegate(string value);
    
    public partial class Form_Server : Form {
        // 静态委托实例,用于更新日志、添加或移除客户端
        public static ShowServerLogDelegate _ShowServerLogEvent = null;
        public static AddListDelegate _AddListEvent = null;
        public static RemoveListDelegate _RemoveListEvent = null;
 
        // TCP服务器实例
        TcpIp_Server tcpIp_Server;
        string ip;  // 服务器IP地址
        int port;  // 服务器端口
        string msg;  // 用于存储消息
        Form_Client form_Client;  // 客户端窗体实例
        String[] clientList;  // 当前连接的客户端列表
 
        // 构造函数,初始化窗体
        public Form_Server() {
            InitializeComponent();
        }
 
        // 窗体加载时执行的操作
        private void Form_Server_Load(object sender, EventArgs e) {
            // 订阅日志、添加客户端和移除客户端事件
            _ShowServerLogEvent += ShowServerLog;
            _AddListEvent += AddList;
            _RemoveListEvent += RemoveList;
 
            // 获取本机的IP地址并添加到ComboBox控件
            GetIP();
            
            // 设置默认端口为5000
            port = int.Parse(textBox_Port.Text = "5000");
        }
 
        // 获取本机所有的IP地址,并将IPv4地址添加到IP地址选择框
        private void GetIP() {
            string name = Dns.GetHostName();  // 获取主机名
            IPAddress[] iPAddress = Dns.GetHostAddresses(name);  // 获取所有IP地址
            foreach (IPAddress item in iPAddress) {
                // 只添加IPv4地址到ComboBox中
                if (item.AddressFamily == AddressFamily.InterNetwork)
                    comboBox_IP.Items.Add(item.ToString());
            }
            // 设置默认选择为第一个IP地址
            comboBox_IP.SelectedIndex = 0;
        }
 
        // 开始监听按钮点击事件
        private void button_Listen_Click(object sender, EventArgs e) {
            // 检查是否已输入IP和端口
            if (comboBox_IP.SelectedItem == null || textBox_Port.Text == "")
            {
                MessageBox.Show("请输入IP和Port!");
                return;
            }
            
            ip = comboBox_IP.SelectedItem.ToString();  // 获取选择的IP地址
            port = int.Parse(textBox_Port.Text);  // 获取端口号
            
            // 创建TCP服务器实例并初始化
            tcpIp_Server = new TcpIp_Server(ip, port);
            _ShowServerLogEvent($"[Info] 服务器初始化完成");
 
            // 启动服务器监听
            _ShowServerLogEvent($"[Info] 服务器开始监听...");
            if(tcpIp_Server.Bind(ref msg))
                button_Listen.BackColor = Color.YellowGreen;  // 设置监听按钮颜色为绿色
            _ShowServerLogEvent($"{msg}");  // 显示监听状态消息
        }
 
        // 停止监听按钮点击事件
        private void Button_ShutDown_Click(object sender, EventArgs e) {
            // 停止服务器监听
            _ShowServerLogEvent($"[Info] 服务器停止监听...");
            tcpIp_Server.ShutDown(clientList, ref msg);
            listBox_Client.Items.Clear();  // 清空客户端列表
            label_ClientCount.Text = "0";  // 更新客户端数量显示
            button_Listen.BackColor = Color.LightGray;  // 恢复监听按钮颜色
            _ShowServerLogEvent($"{msg}");  // 显示停止监听的消息
        }
 
        // 单个客户端发送消息按钮点击事件
        private void Button_SendOnce_Click(object sender, EventArgs e) {
            // 检查是否选择了客户端
            if (listBox_Client.SelectedIndex == -1) {
                MessageBox.Show(new Form { TopMost = true }, $"请选择客户端!", "Error");
                return;
            }
 
            // 获取选择的客户端和消息内容
            _ShowServerLogEvent($"[Info] 服务器单发送信息...");
            string client = listBox_Client.SelectedItem.ToString();
            string cmd = textBox_Message.Text;
            
            // 向客户端发送消息
            tcpIp_Server.SendToClient(client, cmd, ref msg);
            _ShowServerLogEvent($"{msg}");  // 显示发送状态消息
        }
 
        // 向所有客户端发送消息按钮点击事件
        private void button_SendAll_Click(object sender, EventArgs e) {
            _ShowServerLogEvent($"[Info] 服务器多发送信息...");
            string cmd = textBox_Message.Text;  // 获取消息内容
            for (int i = 0; i < listBox_Client.Items.Count; i++) {
                // 向所有客户端发送消息
                tcpIp_Server.SendToClient(listBox_Client.Items[i].ToString(), cmd, ref msg);
                _ShowServerLogEvent($"{msg}");  // 显示每次发送的消息
            }
        }
 
        // 清空日志按钮点击事件
        private void Button_Clear_Click(object sender, EventArgs e) {
            richTextBox_Log.Text = "";  // 清空日志框
        }
 
        // 打开客户端按钮点击事件(目前被注释掉)
        private void button_OpenClient_Click(object sender, EventArgs e) {
            // 这里的代码被注释掉,表示当前功能未启用
            //if (form_Client == null || form_Client.IsDisposed) {
            //    form_Client = new Form_Client();
            //    form_Client.Show();
            //}
            //else {
            //    form_Client.TopMost = true;
            //}
        }
 
        // 服务器窗体关闭时的处理
        private void Form_Server_FormClosing(object sender, FormClosingEventArgs e) {
            // 确保在窗体关闭时关闭服务器
            if (tcpIp_Server != null)
                tcpIp_Server.ShutDown(clientList, ref msg);
            _ShowServerLogEvent($"{msg}");  // 显示服务器关闭消息
            _ShowServerLogEvent -= ShowServerLog;  // 取消订阅日志事件
        }
 
        // 显示服务器日志的方法(线程安全更新UI)
        private void ShowServerLog(string message) {
            if (InvokeRequired) {
                this.BeginInvoke(new Action(() => ShowServerLog(message)));  // 在UI线程更新日志
            }
            else {
                int maxLine = 100;  // 设置日志最大行数
                if (this.richTextBox_Log.Lines.Length > maxLine) {
                    // 如果日志行数超过最大行数,删除最旧的日志
                    this.richTextBox_Log.Text = richTextBox_Log.Text.Substring(richTextBox_Log.Lines[0].Length + 1);
                }
                // 在日志框中追加新的日志
                richTextBox_Log.AppendText($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss(fff)")} {message}\r\n");
                richTextBox_Log.SelectionStart = richTextBox_Log.Text.Length;
                richTextBox_Log.ScrollToCaret();  // 滚动到日志的最新位置
            }
        }
 
        // 向客户端列表中添加客户端(线程安全操作)
        private void AddList(string value) {
            if (InvokeRequired) {
                this.BeginInvoke(new Action(() => AddList(value)));  // 在UI线程更新客户端列表
            }
            else {
                listBox_Client.Items.Add(value);  // 添加客户端到列表
                // 更新客户端列表数组
                clientList = new String[listBox_Client.Items.Count];
                int i = 0;
                foreach (var item in listBox_Client.Items) {
                    clientList[i] = item.ToString();
                }
                label_ClientCount.Text = clientList.Length.ToString();  // 更新客户端数量显示
            }
        }
 
        // 从客户端列表中移除客户端(线程安全操作)
        private void RemoveList(string value) {
            if (InvokeRequired) {
                this.BeginInvoke(new Action(() => RemoveList(value)));  // 在UI线程更新客户端列表
            }
            else {
                listBox_Client.Items.Remove(value);  // 从列表中移除客户端
                // 更新客户端列表数组
                int i = 0;
                foreach (var item in listBox_Client.Items) {
                    clientList[i] = item.ToString();
                }
                label_ClientCount.Text = clientList.Length.ToString();  // 更新客户端数量显示
            }
        }
    }
}

功能解析:

服务器配置与启动:选择IP地址和端口,启动服务器监听客户端连接。
客户端管理:显示连接的客户端,支持单个或所有客户端发送消息。
日志记录:实时显示服务器日志,记录连接、消息发送等操作。
停止服务器:停止监听,清空客户端列表,断开连接。

客户端实现

服务器端实现完成后,接下来我们来实现TCP客户端。客户端界面代码与服务器端类似,主要使用以下类:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace TCPIP_Test {
    // 定义TCP客户端类
    public class TcpIp_Client {
        // 客户端Socket对象,用于与服务器建立TCP连接
        Socket clientSocket;
        // 服务器的IP地址
        string _IP;
        // 服务器的端口
        int _Port;
        // 服务器的IPAddress对象
        IPAddress _ipAddress;
        // 服务器的IPEndPoint对象,包含IP地址和端口
        IPEndPoint _iPEndPoint;
        // 标识连接状态
        bool linked = false;
        // 标识是否曾经断开连接
        bool unlinked = false;
 
        // 构造函数,初始化IP地址和端口
        public TcpIp_Client(string ip, int port) {
            clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 创建TCP连接的Socket对象
            _IP = ip; // 设置IP地址
            _Port = port; // 设置端口号
            _ipAddress = IPAddress.Parse(ip); // 将字符串IP地址解析为IPAddress对象
            _iPEndPoint = new IPEndPoint(_ipAddress, port); // 创建端点对象,包含IP地址和端口
        }
 
        // 当前连接状态
        private bool _Connected;
        public bool Connected {
            get { return _Connected = clientSocket.Connected; } // 返回Socket的连接状态
        }
 
        // 连接到服务器
        public bool ConnectServer(ref string msg) {
            try {
                if (!linked) { // 如果没有连接
                    if (unlinked) {
                        // 如果曾经断开连接,重新创建Socket
                        clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    }
                    // 连接到服务器
                    clientSocket.Connect(_iPEndPoint);
                    if (clientSocket.Connected) { // 如果连接成功
                        linked = true; // 设置连接状态为已连接
                        msg = $"[Info] 服务器{clientSocket.LocalEndPoint.ToString()}连接成功!"; // 设置成功消息
                        ReceiveData(); // 调用方法开始接收数据
                        return true;
                    } else { // 如果连接失败
                        msg = $"[Info] 客户端连接失败!";
                        return false;
                    }
                } else { // 如果已经连接
                    msg = $"[Info] 已连接";
                    return true;
                }
            }
            catch (Exception ex) {
                msg = $"[Err] 连接失败!信息={ex}"; // 连接失败时设置错误消息
                return false;
            }
        }
 
        // 断开与服务器的连接
        public bool DisConnectServer(ref string msg) {
            try {
                if (linked) { // 如果已连接
                    linked = false; // 设置连接状态为未连接
                    clientSocket.Disconnect(false); // 断开连接并释放资源
                    unlinked = true; // 标记为已断开
                    msg = $"[Info] 客户端连接断开";
                    return true;
                } else { // 如果已经是断开状态
                    msg = $"[Info] 已断开";
                    return true;
                }
            }
            catch (Exception ex) {
                msg = $"[Err] 断开失败!信息={ex}"; // 断开连接失败时设置错误消息
                return false;
            }
        }
 
        // 向服务器发送消息
        public bool SendToServer(string cmd, ref string msg) {
            try {
                if (clientSocket.Connected) { // 如果已连接
                    clientSocket.Send(Encoding.UTF8.GetBytes(cmd)); // 将命令转换为字节并发送
                    msg = $"[Info] 发送{clientSocket.LocalEndPoint.ToString()}信息={cmd}"; // 设置发送成功的消息
                    return true;
                } else { // 如果未连接
                    MessageBox.Show(new Form { TopMost = true }, "未连接!", "Info", MessageBoxButtons.OK); // 弹出提示框
                    msg = $"未连接!";
                    return false;
                }
            }
            catch (Exception ex) {
                msg = $"[Err] 发送信息失败!信息={ex}"; // 发送失败时设置错误消息
                return false;
            }
        }
 
        // 接收来自服务器的数据
        private void ReceiveData() {
            string str = ""; // 存储接收到的消息
            Task.Run(() => {
                while (linked) { // 只要连接保持有效,就持续接收数据
                    try {
                        if (clientSocket.Connected) {
                            Thread.Sleep(10); // 为了避免占用过多的CPU时间,稍微暂停一下
                        } else {
                            continue; // 如果连接断开,继续检查连接状态
                        }
                        byte[] data = new byte[1024]; // 缓冲区用于接收数据
                        int length = clientSocket.Receive(data); // 接收服务器发送的数据
                        string message = Encoding.UTF8.GetString(data, 0, length); // 将接收到的字节数据转换为字符串
                        if (message != "") {
                            str = message; // 存储接收到的消息
                            Form_Client._ShowClientLog($"[Info] 接收服务器{clientSocket.LocalEndPoint.ToString()}信息={message}"); // 显示接收到的消息
                        }
                    }
                    catch (Exception ex) {
                        Form_Client._ShowClientLog($"[Err] 接收服务器信息失败!信息={ex}"); // 如果接收失败,显示错误信息
                    }
                }
            });
        }
    }
}

代码解析:

TcpIp_Client类:该类用于实现一个TCP客户端,提供连接服务器、断开连接、发送消息、接收消息等功能。
构造函数:接受服务器的IP地址和端口号,初始化Socket并创建连接端点(IPEndPoint)。
ConnectServer方法:建立与服务器的TCP连接。连接成功后,启动接收数据的线程。
DisConnectServer方法:断开与服务器的连接并释放相关资源。
SendToServer方法:将给定的命令发送到服务器。
ReceiveData方法:接收来自服务器的消息,并在接收到数据时将其打印到客户端界面或日志中。
关键技术:
Socket编程:使用Socket类进行TCP连接的建立、数据的发送和接收。
多线程:ReceiveData方法通过Task.Run()启动一个新的线程来异步接收数据。
消息编码:使用UTF8对消息进行编码和解码。

客户端界面的实现代码如下:

using System;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
 
namespace TCPIP_Test
{
    // 定义一个委托,用于显示客户端日志信息
    public delegate void EventShowClientLog(string message);
 
    // 客户端窗口类
    public partial class Form_Client : Form
    {
        // 声明委托实例,用于日志显示
        public static EventShowClientLog _ShowClientLog = null;
        
        // TCP客户端实例
        TcpIp_Client tcpIp_Client;
        
        // 存储IP地址和端口
        string ip;
        int port;
        string msg;
        
        // 服务器窗口实例
        Form_Server form_Server;
 
        // 构造函数,初始化组件
        public Form_Client()
        {
            InitializeComponent();
        }
 
        // 窗体加载时的事件处理
        private void Form1_Load(object sender, EventArgs e)
        {
            // 绑定委托到日志显示方法
            _ShowClientLog += ShowClientLog;
 
            // 获取本机IP地址并填充到下拉框中
            GetIP();
 
            // 默认端口5000
            port = int.Parse(textBox_Port.Text = "5000");
        }
 
        // 获取本机IP地址的方法
        private void GetIP()
        {
            // 获取本机的计算机名
            string name = Dns.GetHostName();
 
            // 获取所有IP地址
            IPAddress[] iPAddress = Dns.GetHostAddresses(name);
 
            // 遍历所有IP地址,只添加IPv4地址到下拉框中
            foreach (IPAddress item in iPAddress)
            {
                if (item.AddressFamily == AddressFamily.InterNetwork)
                    comboBox_IP.Items.Add(item.ToString());
            }
 
            // 默认选择第一个IP地址
            comboBox_IP.SelectedIndex = 0;
        }
 
        // 连接按钮点击事件处理
        private void Button_Connect_Click(object sender, EventArgs e)
        {
            // 判断是否选择了IP地址和端口
            if (comboBox_IP.SelectedItem == null || textBox_Port.Text == "")
            {
                MessageBox.Show("请输入IP和Port!");
                return;
            }
 
            // 获取选择的IP和端口
            ip = comboBox_IP.SelectedItem.ToString();
            port = int.Parse(textBox_Port.Text);
 
            // 创建TCP客户端实例并尝试连接到服务器
            tcpIp_Client = new TcpIp_Client(ip, port);
            _ShowClientLog($"[Info] 客户端初始化完成");
 
            _ShowClientLog($"[Info] 客户端开始连接...");
 
            // 尝试连接服务器
            if (tcpIp_Client.ConnectServer(ref msg))
                button_Connect.BackColor = Color.YellowGreen; // 连接成功后,改变按钮颜色
            _ShowClientLog($"{msg}");
        }
 
        // 断开连接按钮点击事件处理
        private void Button_DisConnect_Click(object sender, EventArgs e)
        {
            _ShowClientLog($"[Info] 客户端断开连接...");
            
            // 调用断开连接方法
            tcpIp_Client.DisConnectServer(ref msg);
            
            button_Connect.BackColor = Color.LightGray; // 断开连接后,恢复按钮颜色
            _ShowClientLog($"{msg}");
        }
 
        // 发送一次数据按钮点击事件处理
        private void Button_SendOnce_Click(object sender, EventArgs e)
        {
            _ShowClientLog($"[Info] 客户端发送信息...");
 
            // 获取输入框中的信息
            string cmd = textBox_Message.Text;
 
            // 发送数据到服务器
            tcpIp_Client.SendToServer(cmd, ref msg);
            _ShowClientLog($"{msg}");
        }
 
        // 显示日志信息的方法
        private void ShowClientLog(string message)
        {
            // 判断是否需要在UI线程中更新
            if (richTextBox_Log.InvokeRequired)
            {
                EventShowClientLog d = new EventShowClientLog(ShowClientLog);
                richTextBox_Log.Invoke(d, new object[] { message });
            }
            else
            {
                // 最大显示行数限制
                int maxLine = 100;
 
                // 如果超过最大行数,删除最旧的日志行
                if (this.richTextBox_Log.Lines.Length > maxLine)
                {
                    this.richTextBox_Log.Text = richTextBox_Log.Text.Substring(richTextBox_Log.Lines[0].Length + 1);
                }
 
                // 添加日志到文本框,并显示当前时间戳
                richTextBox_Log.AppendText($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss(fff)")} {message}\r\n");
 
                // 滚动到文本框底部
                richTextBox_Log.SelectionStart = richTextBox_Log.Text.Length;
                richTextBox_Log.ScrollToCaret();
            }
        }
 
        // 清除日志按钮点击事件处理
        private void Button_Clear_Click(object sender, EventArgs e)
        {
            // 清空日志显示框
            richTextBox_Log.Text = "";
        }
 
        // 打开服务器窗口按钮点击事件处理
        private void button_OpenServer_Click(object sender, EventArgs e)
        {
            // 如果服务器窗口不存在或已关闭,则新建一个服务器窗口
            if (form_Server == null || form_Server.IsDisposed)
            {
                form_Server = new Form_Server();
                form_Server.Show();
            }
            else
            {
                // 如果服务器窗口已经打开,确保它位于最前面
                form_Server.TopMost = true;
            }
        }
    }
}

代码解析:

  • 1.EventShowClientLog 委托   用于线程安全地更新客户端日志。
  • 2.Form1_Load()   加载时获取本机IP地址并填充IP选择框,设置默认端口。
  • 3.GetIP()   获取并显示本机所有IPv4地址。
  • 4.Button_Connect_Click()连接服务器,成功后更新UI显示连接信息。
  • 5.Button_DisConnect_Click()断开与服务器的连接,并显示断开信息。
  • 6.Button_SendOnce_Click()   发送文本框内容到服务器,并显示发送结果。
  • 7.ShowClientLog()   显示日志信息,超出限制时自动删除最旧日志。
  • 8.Button_Clear_Click()  清空日志框内容。
  • 9.button_OpenServer_Click()   打开或显示服务器窗口。

总结

本文介绍了如何使用C#实现TCP客户端和服务器,并通过简单的代码示例展示了如何设置客户端与服务器的通信。通过设置监听端口和获取客户端IP地址,您可以在客户端和服务器之间建立连接并互相发送消息。通过进一步的优化和扩展,您可以实现更为复杂的网络通信功能。

以上就是C#实现TCP客户端和服务器的基本功能的详细内容,更多关于C# TCP客户端和服务器的资料请关注脚本之家其它相关文章!

相关文章

  • C#使用Unity实现剪刀石头布游戏

    C#使用Unity实现剪刀石头布游戏

    这篇文章主要为大家详细介绍了C#语言使用Unity实现剪刀石头布游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • 使用windows控制台调试服务的方法

    使用windows控制台调试服务的方法

    这篇文章主要介绍了使用windows控制台调试服务的方法,需要的朋友可以参考下
    2014-02-02
  • C#调用python.exe使用arcpy方式

    C#调用python.exe使用arcpy方式

    这篇文章主要介绍了C#调用python.exe使用arcpy方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • C# 使用Winform 获取下拉框 选中的值

    C# 使用Winform 获取下拉框 选中的值

    这篇文章主要介绍了C# 使用Winform 获取下拉框 选中的值,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • c#使用csredis操作redis的示例

    c#使用csredis操作redis的示例

    这篇文章主要介绍了c#使用csredis操作redis的示例,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下
    2020-12-12
  • C#程序加密工具.Net Reactor详细教程

    C#程序加密工具.Net Reactor详细教程

    .Net Reacto加密工具是一款强大的 .NET 代码保护和授权管理系统,安全可靠、简单易用,主要用来帮助开发人员保护他们的 .NET 软件产品,本文给大家详细介绍C#程序加密工具.Net Reactor教程,感兴趣的朋友一起看看吧
    2022-02-02
  • 总结C#动态调用WCF接口的两种方法

    总结C#动态调用WCF接口的两种方法

    这篇文章给大家总结了C#动态调用WCF接口的两种方法,大家可以根据自己的需求选择对应的方式,下面来一起看看。
    2016-09-09
  • 利用C#实现网络爬虫

    利用C#实现网络爬虫

    这篇文章主要介绍了利用C#实现网络爬虫,完整的介绍了C#实现网络爬虫详细过程,感兴趣的小伙伴们可以参考一下
    2016-03-03
  • C#实现程序等待延迟执行的方法

    C#实现程序等待延迟执行的方法

    这篇文章主要介绍了C#实现程序等待延迟执行的方法,涉及C#动态链接库的使用及延迟的实现技巧,需要的朋友可以参考下
    2015-09-09
  • C#模拟Http与Https请求框架类实例

    C#模拟Http与Https请求框架类实例

    这篇文章主要介绍了C#模拟Http与Https请求框架类,实例分析了处理http与https请求的方法与信息处理的技巧,需要的朋友可以参考下
    2014-12-12

最新评论