C#实现TCP客户端和服务器的基本功能
作者:数据的世界01
效果展示
服务器端实现
首先,我们实现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客户端和服务器的资料请关注脚本之家其它相关文章!