亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C#實現(xiàn)TCP客戶端和服務(wù)器的基本功能

 更新時間:2024年12月10日 08:53:59   作者:數(shù)據(jù)的世界01  
本文將介紹如何使用C#實現(xiàn)TCP客戶端和服務(wù)器的基本功能,客戶端與服務(wù)器可以相互發(fā)送消息,文章通過代碼講解的非常詳細,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下

效果展示

服務(wù)器端實現(xiàn)

首先,我們實現(xiàn)TCP服務(wù)器。以下是服務(wù)器端所需的類和代碼:

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; // 服務(wù)器端Socket,用于服務(wù)器與客戶端的通信
        Socket clientSocket; // 客戶端Socket,用于與客戶端建立連接
        TcpListener tcpListener; // 負(fù)責(zé)監(jiān)聽客戶端的連接請求
        Thread tcpListenerThread; // 監(jiān)聽連接請求的線程
        Dictionary<string, Socket> dicClientSockets = new Dictionary<string, Socket>(); // 存儲客戶端Socket的集合,以客戶端的IP/端口作為鍵
        Dictionary<string, Thread> dicReceiveMsg = new Dictionary<string, Thread>(); // 存儲每個客戶端接收消息的線程集合
 
        string _IP; // 服務(wù)器的IP地址
        int _Port; // 服務(wù)器的端口
        IPAddress _ipAddress; // 服務(wù)器的IPAddress對象
        EndPoint _endPoint; // 服務(wù)器的端點,包括IP地址和端口
        bool linked = false; // 標(biāo)識服務(wù)器是否已開始監(jiān)聽客戶端連接
        bool unlinked = false; // 標(biāo)識服務(wù)器是否已關(guān)閉連接
 
        // 構(gòu)造函數(shù),初始化服務(wù)器的IP和端口
        public TcpIp_Server(string ip, int port) {
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 初始化Socket對象,使用TCP協(xié)議
            _IP = ip;
            _Port = port;
            _ipAddress = IPAddress.Parse(ip); // 將IP地址字符串轉(zhuǎn)換為IPAddress對象
            _endPoint = new IPEndPoint(_ipAddress, port); // 構(gòu)造服務(wù)器端點
        }
 
        // 判斷服務(wù)器是否已綁定到指定的端口
        private bool _IsBound;
        public bool IsBound {
            get { return _IsBound = serverSocket.IsBound; }
        }
 
        // 判斷服務(wù)器Socket是否已連接
        private bool _Connected;
        public bool Connected {
            get { return _Connected = serverSocket.Connected; }
        }
 
        // 綁定服務(wù)器并開始監(jiān)聽客戶端連接
        public bool Bind(ref string msg) {
            try {
                if (!linked) {
                    tcpListener = new TcpListener(_ipAddress, _Port); // 創(chuàng)建TcpListener對象,綁定IP和端口
                    tcpListener.Start(); // 啟動監(jiān)聽
                    linked = true; // 標(biāo)記已開始監(jiān)聽
                    ThreadStart threadStart = new ThreadStart(ListenConnectRequest); // 創(chuàng)建一個委托,執(zhí)行監(jiān)聽連接請求的方法
                    tcpListenerThread = new Thread(threadStart); // 創(chuàng)建一個新線程來監(jiān)聽客戶端請求
                    tcpListenerThread.IsBackground = true; // 設(shè)置為后臺線程
                    tcpListenerThread.Start(); // 啟動監(jiān)聽線程
                    msg = $"[Info] 服務(wù)器{tcpListener.LocalEndpoint.ToString()}監(jiān)聽成功!"; // 返回監(jiān)聽成功的消息
                    return true;
                }
                else {
                    msg = $"[Info] 已監(jiān)聽"; // 如果已經(jīng)開始監(jiān)聽,則返回已監(jiān)聽消息
                    return true;
                }
            }
            catch (Exception ex) {
                msg = $"[Err] 連接失?。⌒畔?{ex}"; // 如果發(fā)生異常,返回錯誤信息
                return false;
            }
        }
 
        // 斷開與指定客戶端的連接
        public bool DisConnectClient(string client, ref string msg) {
            try {
                if (dicClientSockets.ContainsKey(client)) {
                    dicClientSockets[client].Close(); // 關(guān)閉與客戶端的連接
                    msg = $"[Info] 斷開客戶端{client}連接"; // 返回斷開成功的消息
                    return true;
                }
                else {
                    msg = $"[Info] 客戶端{client}已斷開"; // 如果客戶端已斷開,返回已斷開消息
                    return true;
                }
            }
            catch (Exception ex) {
                msg = $"[Err] 斷開失?。⌒畔?{ex}"; // 如果發(fā)生異常,返回錯誤信息
                return false;
            }
        }
 
        // 關(guān)閉服務(wù)器監(jiān)聽并斷開所有客戶端連接
        public bool ShutDown(string[] clientList, ref string msg) {
            try {
                if (linked) {
                    linked = false; // 標(biāo)記服務(wù)器停止監(jiān)聽
                    tcpListener.Stop(); // 停止TcpListener監(jiān)聽
                    for (int i = 0; i < clientList.Length; i++) {
                        dicClientSockets[clientList[i]].Close(); // 關(guān)閉每個客戶端的連接
                    }
                    msg = $"[Info] 服務(wù)器監(jiān)聽斷開"; // 返回關(guān)閉監(jiān)聽的消息
                    return true;
                }
                else {
                    unlinked = true; // 標(biāo)記已斷開
                    msg = $"[Info] 已斷開"; // 返回已斷開消息
                    return true;
                }
            }
            catch (Exception ex) {
                tcpListener.Stop(); // 停止TcpListener
                unlinked = true; // 標(biāo)記已斷開
                msg = $"[Info] 已斷開!!!"; // 返回關(guān)閉連接的消息
                return false;
            }
        }
 
        // 向指定客戶端發(fā)送數(shù)據(jù)
        public bool SendToClient(string client, string cmd, ref string msg) {
            try {
                if (!string.IsNullOrEmpty(cmd)) {
                    dicClientSockets[client].Send(Encoding.UTF8.GetBytes(cmd)); // 將命令數(shù)據(jù)發(fā)送給客戶端
                    msg = $"[Info] 發(fā)送{client}信息={cmd}"; // 返回發(fā)送成功的消息
                    return true;
                }
                else
                    return false; // 如果命令為空,返回發(fā)送失敗
            }
            catch (Exception ex) {
                msg = $"[Err] 發(fā)送信息失??!信息={ex}"; // 如果發(fā)送失敗,返回錯誤信息
                return false;
            }
        }
 
        // 監(jiān)聽客戶端的連接請求
        private void ListenConnectRequest() {
            while (linked) {
                try {
                    Socket clientSocket = tcpListener.AcceptSocket(); // 等待并接受客戶端連接
                    ParameterizedThreadStart parameterizedThreadStart = new ParameterizedThreadStart(ReceiveData); // 創(chuàng)建接收數(shù)據(jù)的線程委托
                    Thread receiveMsgThread = new Thread(parameterizedThreadStart); // 創(chuàng)建一個線程來接收客戶端數(shù)據(jù)
                    receiveMsgThread.IsBackground = true; // 設(shè)置為后臺線程
                    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] 監(jiān)聽失??!信息={ex}"); // 監(jiān)聽失敗時顯示錯誤日志
                }
            }
        }
 
        // 接收客戶端發(fā)送的數(shù)據(jù)
        public void ReceiveData(Object obj) {
            Socket clientSocket = (Socket)obj; // 將傳入的參數(shù)轉(zhuǎn)換為Socket
            string str = clientSocket.RemoteEndPoint.ToString(); // 獲取客戶端的遠程端點(IP+端口)
            while (true) {
                try {
                    byte[] buffer = new byte[1024 * 1024]; // 創(chuàng)建緩存區(qū),大小為1MB
                    int length = clientSocket.Receive(buffer); // 接收客戶端數(shù)據(jù)
                    string message = Encoding.UTF8.GetString(buffer, 0, length); // 將字節(jié)數(shù)組轉(zhuǎn)換為字符串
                    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; // 退出接收數(shù)據(jù)的循環(huán)
                }
            }
        }
    }
}

代碼解析:

服務(wù)器初始化: 在構(gòu)造函數(shù)中,初始化了服務(wù)器的Socket、監(jiān)聽端口和IP地址。
綁定與監(jiān)聽: Bind() 方法會啟動一個監(jiān)聽線程,等待客戶端連接請求。
客戶端連接管理: 客戶端連接通過 ListenConnectRequest() 方法處理。每當(dāng)有客戶端連接時,創(chuàng)建一個新的線程來接收客戶端數(shù)據(jù)。
發(fā)送與接收數(shù)據(jù): SendToClient() 方法用于發(fā)送數(shù)據(jù)到指定客戶端,而 ReceiveData() 方法則接收客戶端發(fā)送的數(shù)據(jù)。
斷開與關(guān)閉: DisConnectClient() 和 ShutDown() 方法分別用于斷開客戶端連接和關(guān)閉服務(wù)器監(jiān)聽。

接下來是服務(wù)器界面的代碼:

using System;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
 
namespace TCPIP_Test {
    // 委托用于更新服務(wù)器日志
    public delegate void ShowServerLogDelegate(string message);
    // 委托用于向客戶端列表中添加客戶端
    public delegate void AddListDelegate(string value);
    // 委托用于從客戶端列表中移除客戶端
    public delegate void RemoveListDelegate(string value);
    
    public partial class Form_Server : Form {
        // 靜態(tài)委托實例,用于更新日志、添加或移除客戶端
        public static ShowServerLogDelegate _ShowServerLogEvent = null;
        public static AddListDelegate _AddListEvent = null;
        public static RemoveListDelegate _RemoveListEvent = null;
 
        // TCP服務(wù)器實例
        TcpIp_Server tcpIp_Server;
        string ip;  // 服務(wù)器IP地址
        int port;  // 服務(wù)器端口
        string msg;  // 用于存儲消息
        Form_Client form_Client;  // 客戶端窗體實例
        String[] clientList;  // 當(dāng)前連接的客戶端列表
 
        // 構(gòu)造函數(shù),初始化窗體
        public Form_Server() {
            InitializeComponent();
        }
 
        // 窗體加載時執(zhí)行的操作
        private void Form_Server_Load(object sender, EventArgs e) {
            // 訂閱日志、添加客戶端和移除客戶端事件
            _ShowServerLogEvent += ShowServerLog;
            _AddListEvent += AddList;
            _RemoveListEvent += RemoveList;
 
            // 獲取本機的IP地址并添加到ComboBox控件
            GetIP();
            
            // 設(shè)置默認(rèn)端口為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());
            }
            // 設(shè)置默認(rèn)選擇為第一個IP地址
            comboBox_IP.SelectedIndex = 0;
        }
 
        // 開始監(jiān)聽按鈕點擊事件
        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);  // 獲取端口號
            
            // 創(chuàng)建TCP服務(wù)器實例并初始化
            tcpIp_Server = new TcpIp_Server(ip, port);
            _ShowServerLogEvent($"[Info] 服務(wù)器初始化完成");
 
            // 啟動服務(wù)器監(jiān)聽
            _ShowServerLogEvent($"[Info] 服務(wù)器開始監(jiān)聽...");
            if(tcpIp_Server.Bind(ref msg))
                button_Listen.BackColor = Color.YellowGreen;  // 設(shè)置監(jiān)聽按鈕顏色為綠色
            _ShowServerLogEvent($"{msg}");  // 顯示監(jiān)聽狀態(tài)消息
        }
 
        // 停止監(jiān)聽按鈕點擊事件
        private void Button_ShutDown_Click(object sender, EventArgs e) {
            // 停止服務(wù)器監(jiān)聽
            _ShowServerLogEvent($"[Info] 服務(wù)器停止監(jiān)聽...");
            tcpIp_Server.ShutDown(clientList, ref msg);
            listBox_Client.Items.Clear();  // 清空客戶端列表
            label_ClientCount.Text = "0";  // 更新客戶端數(shù)量顯示
            button_Listen.BackColor = Color.LightGray;  // 恢復(fù)監(jiān)聽按鈕顏色
            _ShowServerLogEvent($"{msg}");  // 顯示停止監(jiān)聽的消息
        }
 
        // 單個客戶端發(fā)送消息按鈕點擊事件
        private void Button_SendOnce_Click(object sender, EventArgs e) {
            // 檢查是否選擇了客戶端
            if (listBox_Client.SelectedIndex == -1) {
                MessageBox.Show(new Form { TopMost = true }, $"請選擇客戶端!", "Error");
                return;
            }
 
            // 獲取選擇的客戶端和消息內(nèi)容
            _ShowServerLogEvent($"[Info] 服務(wù)器單發(fā)送信息...");
            string client = listBox_Client.SelectedItem.ToString();
            string cmd = textBox_Message.Text;
            
            // 向客戶端發(fā)送消息
            tcpIp_Server.SendToClient(client, cmd, ref msg);
            _ShowServerLogEvent($"{msg}");  // 顯示發(fā)送狀態(tài)消息
        }
 
        // 向所有客戶端發(fā)送消息按鈕點擊事件
        private void button_SendAll_Click(object sender, EventArgs e) {
            _ShowServerLogEvent($"[Info] 服務(wù)器多發(fā)送信息...");
            string cmd = textBox_Message.Text;  // 獲取消息內(nèi)容
            for (int i = 0; i < listBox_Client.Items.Count; i++) {
                // 向所有客戶端發(fā)送消息
                tcpIp_Server.SendToClient(listBox_Client.Items[i].ToString(), cmd, ref msg);
                _ShowServerLogEvent($"{msg}");  // 顯示每次發(fā)送的消息
            }
        }
 
        // 清空日志按鈕點擊事件
        private void Button_Clear_Click(object sender, EventArgs e) {
            richTextBox_Log.Text = "";  // 清空日志框
        }
 
        // 打開客戶端按鈕點擊事件(目前被注釋掉)
        private void button_OpenClient_Click(object sender, EventArgs e) {
            // 這里的代碼被注釋掉,表示當(dāng)前功能未啟用
            //if (form_Client == null || form_Client.IsDisposed) {
            //    form_Client = new Form_Client();
            //    form_Client.Show();
            //}
            //else {
            //    form_Client.TopMost = true;
            //}
        }
 
        // 服務(wù)器窗體關(guān)閉時的處理
        private void Form_Server_FormClosing(object sender, FormClosingEventArgs e) {
            // 確保在窗體關(guān)閉時關(guān)閉服務(wù)器
            if (tcpIp_Server != null)
                tcpIp_Server.ShutDown(clientList, ref msg);
            _ShowServerLogEvent($"{msg}");  // 顯示服務(wù)器關(guān)閉消息
            _ShowServerLogEvent -= ShowServerLog;  // 取消訂閱日志事件
        }
 
        // 顯示服務(wù)器日志的方法(線程安全更新UI)
        private void ShowServerLog(string message) {
            if (InvokeRequired) {
                this.BeginInvoke(new Action(() => ShowServerLog(message)));  // 在UI線程更新日志
            }
            else {
                int maxLine = 100;  // 設(shè)置日志最大行數(shù)
                if (this.richTextBox_Log.Lines.Length > maxLine) {
                    // 如果日志行數(shù)超過最大行數(shù),刪除最舊的日志
                    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);  // 添加客戶端到列表
                // 更新客戶端列表數(shù)組
                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();  // 更新客戶端數(shù)量顯示
            }
        }
 
        // 從客戶端列表中移除客戶端(線程安全操作)
        private void RemoveList(string value) {
            if (InvokeRequired) {
                this.BeginInvoke(new Action(() => RemoveList(value)));  // 在UI線程更新客戶端列表
            }
            else {
                listBox_Client.Items.Remove(value);  // 從列表中移除客戶端
                // 更新客戶端列表數(shù)組
                int i = 0;
                foreach (var item in listBox_Client.Items) {
                    clientList[i] = item.ToString();
                }
                label_ClientCount.Text = clientList.Length.ToString();  // 更新客戶端數(shù)量顯示
            }
        }
    }
}

功能解析:

服務(wù)器配置與啟動:選擇IP地址和端口,啟動服務(wù)器監(jiān)聽客戶端連接。
客戶端管理:顯示連接的客戶端,支持單個或所有客戶端發(fā)送消息。
日志記錄:實時顯示服務(wù)器日志,記錄連接、消息發(fā)送等操作。
停止服務(wù)器:停止監(jiān)聽,清空客戶端列表,斷開連接。

客戶端實現(xiàn)

服務(wù)器端實現(xiàn)完成后,接下來我們來實現(xiàn)TCP客戶端。客戶端界面代碼與服務(wù)器端類似,主要使用以下類:

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對象,用于與服務(wù)器建立TCP連接
        Socket clientSocket;
        // 服務(wù)器的IP地址
        string _IP;
        // 服務(wù)器的端口
        int _Port;
        // 服務(wù)器的IPAddress對象
        IPAddress _ipAddress;
        // 服務(wù)器的IPEndPoint對象,包含IP地址和端口
        IPEndPoint _iPEndPoint;
        // 標(biāo)識連接狀態(tài)
        bool linked = false;
        // 標(biāo)識是否曾經(jīng)斷開連接
        bool unlinked = false;
 
        // 構(gòu)造函數(shù),初始化IP地址和端口
        public TcpIp_Client(string ip, int port) {
            clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 創(chuàng)建TCP連接的Socket對象
            _IP = ip; // 設(shè)置IP地址
            _Port = port; // 設(shè)置端口號
            _ipAddress = IPAddress.Parse(ip); // 將字符串IP地址解析為IPAddress對象
            _iPEndPoint = new IPEndPoint(_ipAddress, port); // 創(chuàng)建端點對象,包含IP地址和端口
        }
 
        // 當(dāng)前連接狀態(tài)
        private bool _Connected;
        public bool Connected {
            get { return _Connected = clientSocket.Connected; } // 返回Socket的連接狀態(tài)
        }
 
        // 連接到服務(wù)器
        public bool ConnectServer(ref string msg) {
            try {
                if (!linked) { // 如果沒有連接
                    if (unlinked) {
                        // 如果曾經(jīng)斷開連接,重新創(chuàng)建Socket
                        clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    }
                    // 連接到服務(wù)器
                    clientSocket.Connect(_iPEndPoint);
                    if (clientSocket.Connected) { // 如果連接成功
                        linked = true; // 設(shè)置連接狀態(tài)為已連接
                        msg = $"[Info] 服務(wù)器{clientSocket.LocalEndPoint.ToString()}連接成功!"; // 設(shè)置成功消息
                        ReceiveData(); // 調(diào)用方法開始接收數(shù)據(jù)
                        return true;
                    } else { // 如果連接失敗
                        msg = $"[Info] 客戶端連接失?。?;
                        return false;
                    }
                } else { // 如果已經(jīng)連接
                    msg = $"[Info] 已連接";
                    return true;
                }
            }
            catch (Exception ex) {
                msg = $"[Err] 連接失??!信息={ex}"; // 連接失敗時設(shè)置錯誤消息
                return false;
            }
        }
 
        // 斷開與服務(wù)器的連接
        public bool DisConnectServer(ref string msg) {
            try {
                if (linked) { // 如果已連接
                    linked = false; // 設(shè)置連接狀態(tài)為未連接
                    clientSocket.Disconnect(false); // 斷開連接并釋放資源
                    unlinked = true; // 標(biāo)記為已斷開
                    msg = $"[Info] 客戶端連接斷開";
                    return true;
                } else { // 如果已經(jīng)是斷開狀態(tài)
                    msg = $"[Info] 已斷開";
                    return true;
                }
            }
            catch (Exception ex) {
                msg = $"[Err] 斷開失?。⌒畔?{ex}"; // 斷開連接失敗時設(shè)置錯誤消息
                return false;
            }
        }
 
        // 向服務(wù)器發(fā)送消息
        public bool SendToServer(string cmd, ref string msg) {
            try {
                if (clientSocket.Connected) { // 如果已連接
                    clientSocket.Send(Encoding.UTF8.GetBytes(cmd)); // 將命令轉(zhuǎn)換為字節(jié)并發(fā)送
                    msg = $"[Info] 發(fā)送{clientSocket.LocalEndPoint.ToString()}信息={cmd}"; // 設(shè)置發(fā)送成功的消息
                    return true;
                } else { // 如果未連接
                    MessageBox.Show(new Form { TopMost = true }, "未連接!", "Info", MessageBoxButtons.OK); // 彈出提示框
                    msg = $"未連接!";
                    return false;
                }
            }
            catch (Exception ex) {
                msg = $"[Err] 發(fā)送信息失?。⌒畔?{ex}"; // 發(fā)送失敗時設(shè)置錯誤消息
                return false;
            }
        }
 
        // 接收來自服務(wù)器的數(shù)據(jù)
        private void ReceiveData() {
            string str = ""; // 存儲接收到的消息
            Task.Run(() => {
                while (linked) { // 只要連接保持有效,就持續(xù)接收數(shù)據(jù)
                    try {
                        if (clientSocket.Connected) {
                            Thread.Sleep(10); // 為了避免占用過多的CPU時間,稍微暫停一下
                        } else {
                            continue; // 如果連接斷開,繼續(xù)檢查連接狀態(tài)
                        }
                        byte[] data = new byte[1024]; // 緩沖區(qū)用于接收數(shù)據(jù)
                        int length = clientSocket.Receive(data); // 接收服務(wù)器發(fā)送的數(shù)據(jù)
                        string message = Encoding.UTF8.GetString(data, 0, length); // 將接收到的字節(jié)數(shù)據(jù)轉(zhuǎn)換為字符串
                        if (message != "") {
                            str = message; // 存儲接收到的消息
                            Form_Client._ShowClientLog($"[Info] 接收服務(wù)器{clientSocket.LocalEndPoint.ToString()}信息={message}"); // 顯示接收到的消息
                        }
                    }
                    catch (Exception ex) {
                        Form_Client._ShowClientLog($"[Err] 接收服務(wù)器信息失?。⌒畔?{ex}"); // 如果接收失敗,顯示錯誤信息
                    }
                }
            });
        }
    }
}

代碼解析:

TcpIp_Client類:該類用于實現(xiàn)一個TCP客戶端,提供連接服務(wù)器、斷開連接、發(fā)送消息、接收消息等功能。
構(gòu)造函數(shù):接受服務(wù)器的IP地址和端口號,初始化Socket并創(chuàng)建連接端點(IPEndPoint)。
ConnectServer方法:建立與服務(wù)器的TCP連接。連接成功后,啟動接收數(shù)據(jù)的線程。
DisConnectServer方法:斷開與服務(wù)器的連接并釋放相關(guān)資源。
SendToServer方法:將給定的命令發(fā)送到服務(wù)器。
ReceiveData方法:接收來自服務(wù)器的消息,并在接收到數(shù)據(jù)時將其打印到客戶端界面或日志中。
關(guān)鍵技術(shù):
Socket編程:使用Socket類進行TCP連接的建立、數(shù)據(jù)的發(fā)送和接收。
多線程:ReceiveData方法通過Task.Run()啟動一個新的線程來異步接收數(shù)據(jù)。
消息編碼:使用UTF8對消息進行編碼和解碼。

客戶端界面的實現(xiàn)代碼如下:

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;
        
        // 服務(wù)器窗口實例
        Form_Server form_Server;
 
        // 構(gòu)造函數(shù),初始化組件
        public Form_Client()
        {
            InitializeComponent();
        }
 
        // 窗體加載時的事件處理
        private void Form1_Load(object sender, EventArgs e)
        {
            // 綁定委托到日志顯示方法
            _ShowClientLog += ShowClientLog;
 
            // 獲取本機IP地址并填充到下拉框中
            GetIP();
 
            // 默認(rèn)端口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());
            }
 
            // 默認(rèn)選擇第一個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);
 
            // 創(chuàng)建TCP客戶端實例并嘗試連接到服務(wù)器
            tcpIp_Client = new TcpIp_Client(ip, port);
            _ShowClientLog($"[Info] 客戶端初始化完成");
 
            _ShowClientLog($"[Info] 客戶端開始連接...");
 
            // 嘗試連接服務(wù)器
            if (tcpIp_Client.ConnectServer(ref msg))
                button_Connect.BackColor = Color.YellowGreen; // 連接成功后,改變按鈕顏色
            _ShowClientLog($"{msg}");
        }
 
        // 斷開連接按鈕點擊事件處理
        private void Button_DisConnect_Click(object sender, EventArgs e)
        {
            _ShowClientLog($"[Info] 客戶端斷開連接...");
            
            // 調(diào)用斷開連接方法
            tcpIp_Client.DisConnectServer(ref msg);
            
            button_Connect.BackColor = Color.LightGray; // 斷開連接后,恢復(fù)按鈕顏色
            _ShowClientLog($"{msg}");
        }
 
        // 發(fā)送一次數(shù)據(jù)按鈕點擊事件處理
        private void Button_SendOnce_Click(object sender, EventArgs e)
        {
            _ShowClientLog($"[Info] 客戶端發(fā)送信息...");
 
            // 獲取輸入框中的信息
            string cmd = textBox_Message.Text;
 
            // 發(fā)送數(shù)據(jù)到服務(wù)器
            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
            {
                // 最大顯示行數(shù)限制
                int maxLine = 100;
 
                // 如果超過最大行數(shù),刪除最舊的日志行
                if (this.richTextBox_Log.Lines.Length > maxLine)
                {
                    this.richTextBox_Log.Text = richTextBox_Log.Text.Substring(richTextBox_Log.Lines[0].Length + 1);
                }
 
                // 添加日志到文本框,并顯示當(dāng)前時間戳
                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 = "";
        }
 
        // 打開服務(wù)器窗口按鈕點擊事件處理
        private void button_OpenServer_Click(object sender, EventArgs e)
        {
            // 如果服務(wù)器窗口不存在或已關(guān)閉,則新建一個服務(wù)器窗口
            if (form_Server == null || form_Server.IsDisposed)
            {
                form_Server = new Form_Server();
                form_Server.Show();
            }
            else
            {
                // 如果服務(wù)器窗口已經(jīng)打開,確保它位于最前面
                form_Server.TopMost = true;
            }
        }
    }
}

代碼解析:

  • 1.EventShowClientLog 委托   用于線程安全地更新客戶端日志。
  • 2.Form1_Load()   加載時獲取本機IP地址并填充IP選擇框,設(shè)置默認(rèn)端口。
  • 3.GetIP()   獲取并顯示本機所有IPv4地址。
  • 4.Button_Connect_Click()連接服務(wù)器,成功后更新UI顯示連接信息。
  • 5.Button_DisConnect_Click()斷開與服務(wù)器的連接,并顯示斷開信息。
  • 6.Button_SendOnce_Click()   發(fā)送文本框內(nèi)容到服務(wù)器,并顯示發(fā)送結(jié)果。
  • 7.ShowClientLog()   顯示日志信息,超出限制時自動刪除最舊日志。
  • 8.Button_Clear_Click()  清空日志框內(nèi)容。
  • 9.button_OpenServer_Click()   打開或顯示服務(wù)器窗口。

總結(jié)

本文介紹了如何使用C#實現(xiàn)TCP客戶端和服務(wù)器,并通過簡單的代碼示例展示了如何設(shè)置客戶端與服務(wù)器的通信。通過設(shè)置監(jiān)聽端口和獲取客戶端IP地址,您可以在客戶端和服務(wù)器之間建立連接并互相發(fā)送消息。通過進一步的優(yōu)化和擴展,您可以實現(xiàn)更為復(fù)雜的網(wǎng)絡(luò)通信功能。

以上就是C#實現(xiàn)TCP客戶端和服務(wù)器的基本功能的詳細內(nèi)容,更多關(guān)于C# TCP客戶端和服務(wù)器的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#獲取視頻某一幀的縮略圖的方法

    C#獲取視頻某一幀的縮略圖的方法

    這篇文章主要介紹了C#獲取視頻某一幀的縮略圖的方法,涉及執(zhí)行CMD命令及針對視頻文件操作的技巧,具有一定的實用價值,需要的朋友可以參考下
    2014-11-11
  • C#中LinkedList<T>的存儲結(jié)構(gòu)詳解

    C#中LinkedList<T>的存儲結(jié)構(gòu)詳解

    這篇文章主要介紹了深度解析C#中LinkedList<T>的存儲結(jié)構(gòu),本文將從鏈表的基礎(chǔ)特性、C#中LinkedList的底層實現(xiàn)邏輯,.NET的不同版本對于Queue的不同實現(xiàn)方式的原因分析等幾個視角進行簡單的解讀,需要的朋友可以參考下
    2023-12-12
  • C++中#include頭文件的示例詳解

    C++中#include頭文件的示例詳解

    在C++中,所有的文件操作,都是以流(stream)的方式進行的,fstream也就是文件流file stream。這篇文章主要介紹了C++中#include頭文件,需要的朋友可以參考下
    2020-02-02
  • C#字體池技術(shù)實現(xiàn)代碼詳解

    C#字體池技術(shù)實現(xiàn)代碼詳解

    在本篇文章里小編給大家整理的是關(guān)于C#字體池技術(shù)實現(xiàn)代碼詳解內(nèi)容,有需要的朋友們可以學(xué)習(xí)下。
    2019-11-11
  • 獲取字符串中的漢字拼音首字母

    獲取字符串中的漢字拼音首字母

    獲取字符串中的漢字拼音首字母...
    2007-03-03
  • c#中值類型和引用類型的基礎(chǔ)教程

    c#中值類型和引用類型的基礎(chǔ)教程

    這篇文章主要給大家介紹了關(guān)于c#中值類型和引用類型的基礎(chǔ)教程,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • c#操作xml文件示例

    c#操作xml文件示例

    對于XML讀寫操作,項目中經(jīng)常要用到,之前木有好好總結(jié)過,例如LINQ TO XML也用過,這次無意發(fā)現(xiàn)XPATH對于XML的查詢極為方便,索性把XML的操作總結(jié)以便后續(xù)方便使用
    2014-03-03
  • 使用C#實現(xiàn)讀取PDF中所有文本內(nèi)容

    使用C#實現(xiàn)讀取PDF中所有文本內(nèi)容

    這篇文章主要為大家詳細介紹了如何使用C#實現(xiàn)讀取PDF中所有文本內(nèi)容,文中的示例代碼簡潔易懂,具有一定的學(xué)習(xí)價值,有需要的小伙伴可以了解下
    2024-02-02
  • C#byte數(shù)組傳入C操作方法

    C#byte數(shù)組傳入C操作方法

    在本篇內(nèi)容中小編給大家分享了關(guān)于C#byte數(shù)組傳入C操作方法以及相關(guān)知識點,需要的朋友們學(xué)習(xí)下。
    2019-02-02
  • 詳解C#中Helper類的使用

    詳解C#中Helper類的使用

    項目中用戶頻繁訪問數(shù)據(jù)庫會導(dǎo)致程序的卡頓,甚至堵塞。使用緩存可以有效的降低用戶訪問數(shù)據(jù)庫的頻次,有效的減少并發(fā)的壓力。而helper類對緩存有了封裝,本文展示了封裝的示例代碼,需要的可以參考一下
    2022-04-04

最新評論