最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#基于TCP/IP實現(xiàn)接收并推送數(shù)據(jù)的小工具

 更新時間:2025年11月14日 08:49:06   作者:對號東  
這篇文章主要為大家詳細介紹了C#如何基于TCP/IP實現(xiàn)接收并推送數(shù)據(jù)的小工具,文中的示例代碼講解詳細,感興趣的小伙伴可以了解下

一、前言:基于.NET  C#的「數(shù)據(jù)打通」小幫手

做物聯(lián)網(wǎng)設備聯(lián)調(diào)、服務端數(shù)據(jù)采集時,是不是總遇到這些需求:

  • 用 C# 快速搭建 TCP服務器端、客戶端,和設備 / 服務器建立穩(wěn)定連接
  • 實時接收 TCP 數(shù)據(jù)流,自動推送到業(yè)務 API 接口
  • 斷連自動重試、推送失敗重發(fā),還得有清晰日志方便排查

作為.NET 開發(fā)者,之前用 Python 寫過類似工具,但項目需要 C# 版本,索性重新造個輪子~ 這個工具輕量無依賴,兼顧「連接穩(wěn)定性測試」和「數(shù)據(jù)自動轉發(fā)」,今天把完整思路 + 代碼拆解分享,新手也能直接復用!

當然如果您是需要找一個現(xiàn)成的工具放在windows10/11下直接使用,也可以略過源碼研究,直接拿走發(fā)行版本使用即可。

功能預覽:

二、核心功能 & 技術棧

先明確工具定位,避免功能冗余:

  • TCP 客戶端:支持配置 IP / 端口,斷連自動重試(無需手動重啟)
  • 數(shù)據(jù)接收:實時監(jiān)聽 TCP 流,處理粘包 / 半包(自定義解析規(guī)則)
  • API 推送:異步推送數(shù)據(jù)到目標接口,支持超時設置、失敗重試
  • 日志記錄:記錄連接狀態(tài)、數(shù)據(jù)收發(fā)、API 推送結果(基于.NET 自帶日志)

技術棧(純.NET 原生,無需第三方依賴):

開發(fā)語言:C# (兼容.NET Core 3.1/.>NET4+/NET 5+/.NET 6+)

核心類庫:

  • System.Net.Sockets(TCP 連接與數(shù)據(jù)收發(fā))
  • System.Net.HttpWebRequest(API 請求)

三、核心代碼拆解(帶詳細注釋)

下面分模塊講解,完整代碼可直接拉到文末獲取,復制就能運行~

1. 核心服務器端工具類-TcpServerTool

負責執(zhí)行TCP數(shù)據(jù)接收,并調(diào)用API接口地址將收到的數(shù)據(jù)進行推送。持續(xù)接收數(shù)據(jù),處理斷連重試和粘包問題。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
using System.IO;

namespace JoTcp
{
    internal class TcpServerTool
    {
        #region 事件委托
        /// <summary>
        /// 執(zhí)行操作消息變更
        /// </summary>
        public event EventHandler<string> ExecuteMessageChanged;
        /// <summary>
        /// 客戶端個數(shù)變更
        /// </summary>
        public event EventHandler<string> ClientCountChanged;
        #endregion

        #region 字段、屬性
        private string _ip = "127.0.0.1";           //ip
        private int _port = 9000;                   //端口
        private string _ipPort = "127.0.0.1:9000";  //
        private string _api = "";           //api接口地址
        private bool _isConnected = false;          //是否連接
        private bool _isListened = false;           //是否偵聽
        private NetworkStream _stream;              //網(wǎng)絡基礎流
        private Socket _serverSocket;               //服務端套接字對象
        private Thread listenThread = null;         //偵聽線程
        private List<string> _clientIpPortList = new List<string>();   //客戶端Ip端口集合
        private List<Socket> _clientSocketList = new List<Socket>();    //客戶端套接字對象集合    
        private List<Thread> _clientSocketThreadList = new List<Thread>(); //接收線程:接收客戶端對象集合

        public string IP { get => _ip; set => _ip = value; }
        public int Port { get => _port; set => _port = value; }
        public string API { get => _api; set => _api = value; }
        public bool IsConnected { get => _isConnected; set => _isConnected = value; }
        public bool IsListened { get => _isListened; set => _isListened = value; }
        public NetworkStream Stream { get => _stream; set => _stream = value; }
        public Socket ServerSocket { get => _serverSocket; set => _serverSocket = value; }
        public List<string> ClientIpPortList { get => _clientIpPortList; set => _clientIpPortList = value; }
        public List<Socket> ClientSocketList { get => _clientSocketList; set => _clientSocketList = value; }
        public List<Thread> ClientSocketThreadList { get => _clientSocketThreadList; set => _clientSocketThreadList = value; }
        public string IpPort { get => _ipPort; set => _ipPort = value; }
        #endregion

        #region 構造方法
        public TcpServerTool(string ip, int port,string apiUrl)
        {
            this.IP = ip;
            this.Port = port;
            this.API = apiUrl;
        }
        public TcpServerTool(string ip, string port, string apiUrl)
        {
            this.IP = ip;
            if (int.TryParse(port, out int portStr))
            {
                this.Port = portStr;
            }
            if(apiUrl!= null)
            {
                this.API = apiUrl;
            }
        }
        #endregion

        /// <summary>
        /// 斷開連接
        /// </summary>
        public void Disconnect()
        {

            //Console.WriteLine("關閉。。。");
            try
            {
                //狀態(tài)
                IsListened = false;
                IsConnected = false;

                //Console.WriteLine("關閉2。。。");
                foreach (Thread item in ClientSocketThreadList)
                {
                    item.Abort();
                }
                //關閉對象集合,清除集合項
                foreach (Socket item in ClientSocketList)
                {
                    item.Close();
                }
                //Console.WriteLine("關閉3。。。");



               

                //關閉流
                Stream?.Close();
                Stream = null;


                ServerSocket?.Close();
                ServerSocket = null;


                ClientSocketThreadList?.Clear();
                ClientSocketList?.Clear();
                ClientIpPortList?.Clear();

                //關閉線程
                listenThread?.Abort();
                listenThread = null;

                //Console.WriteLine("關閉4。。。");
            }
            catch (Exception ex)
            {
                ExecuteMessageChanged?.Invoke(this, $"失敗....");
                ExecuteMessageChanged?.Invoke(this, $"{ex.Message}");
            }

        }
        /// <summary>
        /// 服務端打開
        /// </summary>
        public void Open()
        {
            try
            {
                IPAddress ipAddress = IPAddress.Parse(IP);  //IP地址
                // 創(chuàng)建一個新的 Socket 對象,指定為 IPv4、面向流的(TCP)協(xié)議
                ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //允許套接字復用
                ServerSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                // 服務器綁定指定終端(IP,Port)
                IPEndPoint localEndPoint = new IPEndPoint(ipAddress, Port);//創(chuàng)建終端
                ServerSocket.Bind(localEndPoint);   //綁定終端

                ExecuteMessageChanged?.Invoke(this, $"開始偵聽準備...");
                ServerSocket.Listen(10);
                //創(chuàng)建并使用線程偵聽
                listenThread = new Thread(OnListenClient);
                listenThread.IsBackground = true;
                listenThread.Start();
                IsListened = true;

                ExecuteMessageChanged?.Invoke(this, $"本地終端:{ServerSocket.LocalEndPoint}");
                ExecuteMessageChanged?.Invoke(this, $"協(xié)議:{ServerSocket.LocalEndPoint.AddressFamily}");
                ExecuteMessageChanged?.Invoke(this, $"準備完成,開始偵聽客戶端連接...");

            }
            catch (Exception ex)
            {
                ExecuteMessageChanged?.Invoke(this, $"創(chuàng)建連接失敗....");
                ExecuteMessageChanged?.Invoke(this, $"{ex.Message}");
            }
        }

        /// <summary>
        /// 偵聽客戶端
        /// </summary>
        public void OnListenClient()
        {
            try
            {
                while (true)
                {
                    //接受一個客戶端的連接請求
                    Socket socket = ServerSocket.Accept();
                    ExecuteMessageChanged?.Invoke(this, $"收到來自【{socket.LocalEndPoint}】遠程終端的連接請求...");
                    // 發(fā)送消息給客戶端
                    string sendTestData = "JoTCP Connect...";
                    ExecuteMessageChanged?.Invoke(this, $"嘗試發(fā)送數(shù)據(jù):{sendTestData}");
                    Send(socket, sendTestData);

                    //創(chuàng)建接收數(shù)據(jù)線程
                    Thread thread = new Thread(Received);
                    thread.Name = (ClientSocketThreadList.Count + 1) + "";
                    thread.IsBackground = true;
                    thread.Start(socket);

                    //添加對象到集合
                    ClientIpPortList.Add(socket.RemoteEndPoint.ToString());  //添加遠程終端到集合
                    ClientSocketList.Add(socket);                                   //添加Socket對現(xiàn)象到集合
                    ClientSocketThreadList.Add(thread);                             //創(chuàng)建對應的客戶端Socket線程對象并添加到集合

                    //觸發(fā)客戶端個數(shù)變更事件
                    ClientCountChanged?.Invoke("Add", socket.RemoteEndPoint.ToString());
                }
            }
            catch (Exception ex)
            {
                ExecuteMessageChanged?.Invoke(this, $"偵聽異常:{ex.Message}");
            }
        }
        /// <summary>
        /// 接收數(shù)據(jù)方法
        /// </summary>
        public void Received(object socketClientPara)
        {
            Socket socketServer = socketClientPara as Socket;
            string remoteEndPoint = socketServer.RemoteEndPoint.ToString(); ;
            while (true)
            {
                try
                {
                    // 讀取客戶端發(fā)送的數(shù)據(jù)
                    byte[] buffer = new byte[1024 * 1024];
                    if (socketServer == null) break;
                    // 接收客戶端發(fā)來的數(shù)據(jù)
                    int dataLength = socketServer.Receive(buffer);
                    // 將接收的數(shù)據(jù)轉換為字符串并輸出
                    //string dataReceived = Encoding.ASCII.GetString(buffer, 0, dataLength);
                    string dataReceived = Encoding.UTF8.GetString(buffer, 0, dataLength).Trim();
                    ExecuteMessageChanged.Invoke(this, "接收數(shù)據(jù):");
                    ExecuteMessageChanged.Invoke(this, $"{socketServer.RemoteEndPoint}->{dataReceived}");

                     

                    log("接收數(shù)據(jù):" + dataReceived);

                    // 推送數(shù)據(jù)至api接口
                    if (this.API != null && this.API!="")
                    {
                       SendApiData(this.API, dataReceived);
                    }
                }
                catch (Exception ex)
                {
                    if (IsListened)
                    {
                        ClientIpPortList.Remove(remoteEndPoint);
                        ClientCountChanged?.Invoke("Remove", remoteEndPoint);
                        Stream = null;
                        ExecuteMessageChanged.Invoke(this, "客戶端已斷開連接!");
                        ExecuteMessageChanged.Invoke(this, $"接收異常:{ex.Message}");

                        ClientSocketList.Find(s => s.RemoteEndPoint.Equals(remoteEndPoint))?.Close();
                        ClientSocketList.Remove(socketServer);
                        break;
                    }
                }
            }
        }

        /// <summary>
        /// 發(fā)送數(shù)據(jù):根據(jù)指定IpPort,
        /// </summary>
        public void Send(string ipPort, string data)
        {
            try
            {
                if (IsListened)
                {
                    string socketIpPort = ClientIpPortList.Find(s => s.Equals(ipPort));
                    Socket socket = ClientSocketList.Find(s => s.RemoteEndPoint.ToString().Equals(ipPort));
                    if (socket != null)
                    {
                        Stream = new NetworkStream(socket);
                        string dataToSend = data;
                        byte[] dataBytes = Encoding.UTF8.GetBytes(dataToSend);
                        Stream.Write(dataBytes, 0, dataBytes.Length);
                        ExecuteMessageChanged?.Invoke(this, $"發(fā)送數(shù)據(jù)長度:{dataBytes.Length}");
                    }
                    else
                    {
                        ExecuteMessageChanged?.Invoke(this, $"發(fā)送失敗!socket = null");
                    }
                }
            }
            catch (Exception ex)
            {
                ExecuteMessageChanged?.Invoke(this, $"發(fā)送異常:{ex.Message}");
            }
        }
        /// <summary>
        /// 發(fā)送數(shù)據(jù):根據(jù)指定Socket對象
        /// </summary>
        public void Send(Socket socket, string data)
        {
            try
            {
                if (IsListened)
                {
                    if (Stream != null)
                    {
                        string dataToSend = data;
                        byte[] dataBytes = Encoding.UTF8.GetBytes(dataToSend);
                        Stream.Write(dataBytes, 0, dataBytes.Length);
                        ExecuteMessageChanged?.Invoke(this, $"發(fā)送數(shù)據(jù)長度:{dataBytes.Length}");
                    }
                    else
                    {
                        Stream = new NetworkStream(socket);
                        string dataToSend = data;
                        byte[] dataBytes = Encoding.UTF8.GetBytes(dataToSend);
                        Stream.Write(dataBytes, 0, dataBytes.Length);
                        ExecuteMessageChanged?.Invoke(this, $"發(fā)送數(shù)據(jù)長度:{dataBytes.Length}");
                    }
                }
            }
            catch (Exception ex)
            {
                ExecuteMessageChanged?.Invoke(this, $"發(fā)送異常:{ex.Message}");
            }
        }

        /// <summary>
        /// 群發(fā)數(shù)據(jù):發(fā)送數(shù)據(jù)到所有在連接客戶端。
        /// </summary>
        /// <param name="data"></param>
        public void SendGroup(string data)
        {
            try
            {
                if (IsListened)
                {
                    foreach (Socket socket in ClientSocketList)
                    {
                        Stream = new NetworkStream(socket);
                        string dataToSend = data;
                        byte[] dataBytes = Encoding.UTF8.GetBytes(dataToSend);
                        Stream.Write(dataBytes, 0, dataBytes.Length);
                        ExecuteMessageChanged.Invoke(this, $"發(fā)送到終端:{socket.RemoteEndPoint}");
                        ExecuteMessageChanged.Invoke(this, $"協(xié)議版本:{socket.RemoteEndPoint.AddressFamily}");
                        ExecuteMessageChanged.Invoke(this, $"發(fā)送數(shù)據(jù)長度:{dataBytes.Length}");
                    }
                }
            }
            catch (Exception ex)
            {
                ExecuteMessageChanged.Invoke(this, $"發(fā)送異常:{ex.Message}");
            }
        }


        /// <summary>
        /// 推送數(shù)據(jù)到接口
        /// </summary>
        /// <param name="data"></param>
        public void SendApiData(string apiUrl, string data)
        {

            try
            {
                //調(diào)用接口
                String url = apiUrl + "?data=" + Uri.EscapeDataString(data);
                log("推送至:" + url);
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = "GET"; // 設置請求方法為GET
                request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; // 設置接受的內(nèi)容類型,可選
                request.ContentType = "application/x-www-form-urlencoded"; // 如果需要發(fā)送數(shù)據(jù),設置ContentType,此處為GET請求通常不需要設置ContentType,除非有特殊需求
                request.Headers.Add("Accept-Charset", "UTF-8"); // 指定請求內(nèi)容應該使用UTF-8編碼

                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                        {
                            string responseBody = reader.ReadToEnd();
                            //返回信息
                            log("推送結果:"+responseBody);
                            //MessageBox.Show(responseBody);

                        }
                    }
                }
            }
            catch (WebException e)
            {
                //MessageBox.Show($"Error fetching data: {e.Message}");
            }

           
        }
         
        // 日志
        public void log(string msg)
        {

            string logFilePath = "log/" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt"; // 日志文件路徑
            string logMessage = DateTime.Now.ToString() + ": " + msg +"\n"; // 日志內(nèi)容
            File.AppendAllText(logFilePath, logMessage);
        } 



}
}

2. 模擬TCP/IP客戶端工具類-TcpClient

用于實現(xiàn)TCP客戶端模擬測試:

using System;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;

namespace JoTcp
{
    public class TcpClientTool
    {
        #region 字段、屬性
        private string _ip = "127.0.0.1";           //ip
        private int _port = 8000;                   //端口
        private string _ipPort = "127.0.0.1:8000";  //ip端口
        private bool _isConnected = false;          //是否連接
        private Socket _clientSocket;               //套接字
        private Thread receiveThread = null;
        public string IP { get => _ip; set => _ip = value; }
        public int Port { get => _port; set => _port = value; }
        public string IpPort { get => _ipPort; set => _ipPort = value; }
        public bool IsConnected { get => _isConnected; set => _isConnected = value; }
        public Socket ClientSocket { get => _clientSocket; set => _clientSocket = value; }
        #endregion

        #region 事件委托
        /// <summary>
        /// 執(zhí)行(操作)消息變更
        /// </summary>
        public event EventHandler<string> ExecuteMessageChanged;
        #endregion

        /// <summary>
        /// 構造函數(shù)
        /// </summary>
        public TcpClientTool(string ip, string port)
        {
            this.IP = ip;
            if (int.TryParse(port, out int portStr))
            {
                this.Port = portStr;
            }
        }

        /// <summary>
        /// 連接
        /// </summary>
        public void Connect()
        {
            try
            {
                //創(chuàng)建套字節(jié)對象(IP4尋址協(xié)議,流式連接,TCP協(xié)議)
                ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                //設置終端IpPort
                IPAddress ipaddress = IPAddress.Parse(this.IP);
                IPEndPoint endpoint = new IPEndPoint(ipaddress, Port);

                //連接
                ClientSocket.Connect(endpoint);
                IsConnected = true;
                ExecuteMessageChanged.Invoke(this, $"連接成功!");
                Send("A you ok?");

                //接收線程
                receiveThread = new Thread(Received);
                receiveThread.IsBackground = true;
                receiveThread.Start();
            }
            catch (Exception ex)
            {
                receiveThread?.Abort();
                receiveThread = null;
                ClientSocket.Close();
                IsConnected = false;
                ExecuteMessageChanged.Invoke(this, $"連接失敗!{ex.Message}");
            }
        }
        /// <summary>
        /// 斷開連接
        /// </summary>
        public void Disconnect()
        {
            ClientSocket.Close();
            receiveThread?.Abort();
            receiveThread = null;
            IsConnected = false;
            ExecuteMessageChanged.Invoke(this, $"斷開連接!");
        }
        /// <summary>
        /// 發(fā)送
        /// </summary>
        public void Send(string data)
        {
            try
            {
                byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(data);
                //調(diào)用客戶端套接字發(fā)送字節(jié)數(shù)組// 發(fā)送消息到服務器
                ClientSocket.Send(arrClientSendMsg);
                ExecuteMessageChanged.Invoke(this, data);
            }
            catch (Exception ex)
            {
                ExecuteMessageChanged.Invoke(this, $"發(fā)送失敗:{ex.Message}");
            }
        }
        /// <summary>
        /// 接收
        /// </summary>
        public void Received()
        {
            try
            {
                while (true)
                {
                    //定義一個1M的內(nèi)存緩沖區(qū) 用于臨時性存儲接收到的信息
                    byte[] arrRecMsg = new byte[1024 * 1024];
                    //將客戶端套接字接收到的數(shù)據(jù)存入內(nèi)存緩沖區(qū), 并獲取其長度
                    int length = ClientSocket.Receive(arrRecMsg);
                    //將套接字獲取到的字節(jié)數(shù)組轉換為人可以看懂的字符串
                    string strRecMsg = Encoding.UTF8.GetString(arrRecMsg, 0, length);
                    //將發(fā)送的信息追加到聊天內(nèi)容文本框中
                    ExecuteMessageChanged.Invoke(this, $"{ClientSocket.RemoteEndPoint}->:{strRecMsg}");
                }
            }
            catch (Exception ex)
            {
                ExecuteMessageChanged.Invoke(this, $"遠程服務器已中斷連接...{ex.Message}");
            }
        }

    }
}

3. INI簡易配置管理工具類-JoTcp

負責執(zhí)行config.ini配置文件編輯:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace JoTcp
{
    // 單層簡單ini讀取
    internal class JoIniConfig
    {
        
        private IniFile iniFile;

        public JoIniConfig(string filename="config.ini")
        { 
            //string basePath = System.IO.Directory.GetCurrentDirectory(); // 當前工作目錄
            //string fullPath = System.IO.Path.Combine(basePath, filename); // 構建完整路徑
            
            iniFile = new IniFile(filename);

        }
       

        public string Get(string key)
        {
            return iniFile.GetValue(key);

        }
        public void Set( string key, string value)
        {
            iniFile.SetValue(key, value);

        }

        public void Save()
        {
            iniFile.Save();
        }

    }
      

    /// <summary>
    /// 純C#實現(xiàn)的單層INI配置文件讀寫工具(無節(jié)[Section],僅鍵值對)
    /// </summary>
    public class IniFile
    {
        private readonly string _filePath;
        private Dictionary<string, string> _keyValues;

        /// <summary>
        /// 初始化INI文件操作類
        /// </summary>
        /// <param name="filePath">INI文件路徑</param>
        public IniFile(string filePath)
        {
            _filePath = filePath;
            _keyValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); // 忽略鍵的大小寫
            Load(); // 加載文件內(nèi)容
        }

        /// <summary>
        /// 從文件加載配置
        /// </summary>
        private void Load()
        {
            if (!File.Exists(_filePath))
            {
                _keyValues.Clear();
                return;
            }

            // 讀取所有行并解析
            var lines = File.ReadAllLines(_filePath);
            foreach (var line in lines)
            {
                string trimmedLine = line.Trim();
                // 跳過空行和注釋(;或#開頭)
                if (string.IsNullOrEmpty(trimmedLine) || trimmedLine.StartsWith(";") || trimmedLine.StartsWith("#"))
                    continue;

                // 分割鍵值對(取第一個=作為分隔符)
                int eqIndex = trimmedLine.IndexOf('=');
                if (eqIndex <= 0)
                    continue; // 無效格式(無鍵或無=)

                string key = trimmedLine.Substring(0, eqIndex).Trim();
                string value = trimmedLine.Substring(eqIndex + 1).Trim();

                if (!string.IsNullOrEmpty(key))
                {
                    _keyValues[key] = value; // 覆蓋已有鍵
                }
            }
        }

        /// <summary>
        /// 保存配置到文件
        /// </summary>
        public void Save()
        {
            // 確保目錄存在
            string directory = Path.GetDirectoryName(_filePath);
            if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }

            // 寫入所有鍵值對
            var lines = _keyValues.Select(kv => $"{kv.Key}={kv.Value}").ToList();
            File.WriteAllLines(_filePath, lines);
        }

        /// <summary>
        /// 讀取指定鍵的值
        /// </summary>
        /// <param name="key">鍵名</param>
        /// <param name="defaultValue">默認值(鍵不存在時返回)</param>
        /// <returns>鍵對應的值</returns>
        public string GetValue(string key, string defaultValue = "")
        {
            return _keyValues.TryGetValue(key, out string value) ? value : defaultValue;
        }

        /// <summary>
        /// 寫入鍵值對(若鍵已存在則覆蓋)
        /// </summary>
        /// <param name="key">鍵名</param>
        /// <param name="value">值</param>
        public void SetValue(string key, string value)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentException("鍵名不能為空", nameof(key));

            _keyValues[key] = value ?? string.Empty; // 處理null值
        }

        /// <summary>
        /// 刪除指定鍵
        /// </summary>
        /// <param name="key">鍵名</param>
        /// <returns>是否刪除成功(鍵存在則返回true)</returns>
        public bool DeleteKey(string key)
        {
            return _keyValues.Remove(key);
        }

        /// <summary>
        /// 檢查鍵是否存在
        /// </summary>
        /// <param name="key">鍵名</param>
        /// <returns>是否存在</returns>
        public bool ContainsKey(string key)
        {
            return _keyValues.ContainsKey(key);
        }

        /// <summary>
        /// 獲取所有鍵值對
        /// </summary>
        /// <returns>鍵值對字典</returns>
        public Dictionary<string, string> GetAllKeys()
        {
            return new Dictionary<string, string>(_keyValues); // 返回副本,避免外部修改
        }
    }
}

4. 推送服務端窗口模塊-Frm_TcpServer

程序服務執(zhí)行窗口界面,服務核心程序運行界面:

using System;
using System.Configuration;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace JoTcp
{
    public partial class Frm_TcpServer : Form
    {

        TcpServerTool tcpServerTool;
        JoIniConfig config = new JoIniConfig();
        public Frm_TcpServer()
        {
            InitializeComponent();
        }


        #region 窗體:初始化、加載、關閉
   
        private void Frm_TcpServer_Load(object sender, EventArgs e)
        {
            tbx_IpAddress.Text = config.Get("ip");
            tbx_Port.Text = config.Get("port");
            tbx_apiUrl.Text = config.Get("apiurl");


            ControlStyleUpdata(picBox_ConnectStatu, Color.Gray);
        }
        private void Frm_TcpServer_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (tcpServerTool != null)
            {
                tcpServerTool.Disconnect();
            }
        }
        #endregion

        #region 控件圓角方法
        public void ControlStyleUpdata(Control control)
        {
            GraphicsPath gp = new GraphicsPath();
            gp.AddEllipse(control.ClientRectangle);
            Region region = new Region(gp);
            control.Region = region;
            gp.Dispose();
            region.Dispose();
        }
        public void ControlStyleUpdata(Control control, Color bcColor)
        {
            control.BackColor = bcColor;
            ControlStyleUpdata(control);
        }
        #endregion

        #region 鼠標單擊事件
        private void btn_Open_Click(object sender, EventArgs e)
        {
            bool isOpen = btn_Open.Text.Equals("打開") ? true : false;
            if (isOpen)
            {
                tcpServerTool = new TcpServerTool(tbx_IpAddress.Text, tbx_Port.Text, tbx_apiUrl.Text);
                tcpServerTool.ExecuteMessageChanged += TcpTool_ExecuteMessageChangedCallback;
                tcpServerTool.ClientCountChanged += TcpTool_OnCountChangedCallback;
                tcpServerTool.Open();
            }
            else
            {
                tcpServerTool.Disconnect();
            }

            //設置顯示燈狀態(tài)
            if (tcpServerTool.IsListened) picBox_ConnectStatu.BackColor = Color.LimeGreen;
            else picBox_ConnectStatu.BackColor = Color.Gray;
            btn_Open.Text = tcpServerTool.IsListened ? "關閉" : "打開";
        }
        private void btn_Send_Click(object sender, EventArgs e)
        {
            if (tcpServerTool != null)
            {
                if (checkBox_SendGroup.Checked)
                {
                    tcpServerTool.SendGroup(rtbx_SendData.Text);
                }
                else
                {
                    tcpServerTool.Send(cbx_ClientList.Text, rtbx_SendData.Text);
                }
            }
        }
        private void btn_ClearReceiveData_Click(object sender, EventArgs e)
        {
            rtbx_ReceiveData.Text = string.Empty;
        }
        private void btn_ClearSendData_Click(object sender, EventArgs e)
        {
            rtbx_SendData.Text = string.Empty;
        }
        #endregion

        /// <summary>
        /// 執(zhí)行(操作)消息
        /// </summary>
        private void TcpTool_ExecuteMessageChangedCallback(object sender, string message)
        {
            MessageShow(message);
        }
        /// <summary>
        /// 客戶端數(shù)量變更事件:
        ///     參數(shù)1:執(zhí)行模式(Add,Remove)
        ///     參數(shù)2:終端(IpPort)
        /// </summary>
        public void TcpTool_OnCountChangedCallback(object sender, string endPoint)
        {
            MessageShow($"{sender}:{endPoint}");
            ClientListUpdata(endPoint, sender.ToString());
        }
        /// <summary>
        /// 顯示消息到文本控件
        /// </summary>
        public void MessageShow(string data)
        {
            rtbx_ReceiveData.Invoke(new Action(() =>
            {
                rtbx_ReceiveData.AppendText($"{DateTime.Now}】{data}{System.Environment.NewLine}");
            }));
        }
        /// <summary>
        /// 客戶端列表更新
        /// </summary>
        public void ClientListUpdata(string endPoint, string mode)
        {
            cbx_ClientList.Invoke(new Action(() =>
            {
                switch (mode.ToString().ToLower())
                {
                    case "add":
                        cbx_ClientList.Items.Add(endPoint);
                        break;
                    case "remove":
                        cbx_ClientList.Items.Remove(endPoint);
                        break;
                    default:
                        break;
                }
                if (cbx_ClientList.Items.Count == 1) cbx_ClientList.SelectedIndex = 0;
                if (cbx_ClientList.Items.Count == 0) cbx_ClientList.Text = string.Empty;
            }));
        }

        private void btn_save_Click(object sender, EventArgs e)
        {
           config.Set("ip", tbx_IpAddress.Text);
           config.Set("port", tbx_Port.Text);
           config.Set("apiurl", tbx_apiUrl.Text);
           config.Save();


            MessageBox.Show("當前設置已保存為默認,下次打開直接可用。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);


        }

        // 獲取appsetting
        public string configGet(string keyName)
        {
            //返回配置文件中鍵為keyName的項的值
            return ConfigurationManager.AppSettings[keyName];
        }

        // 修改、新增、設置 appsetting
        public void configSet(string keyName, string newKeyValue)
        {
            //修改配置文件中鍵為keyName的項的值
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            config.AppSettings.Settings[keyName].Value = newKeyValue;
            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");
        }
    }
}

4. 模擬客戶端窗口模塊-Frm_TcpClient

模擬客戶端執(zhí)行窗口界面:

using JoTcp;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace JoTcp
{

    public partial class Frm_TcpClient : Form
    {
        TcpClientTool tcpTool;
        JoIniConfig config = new JoIniConfig();


        #region 窗體:初始化、加載、關閉
        public Frm_TcpClient()
        {
            InitializeComponent();

        }
        private void Frm_TcpClient_Load(object sender, EventArgs e)
        {

            tbx_IpAddress.Text = config.Get("ip");
            tbx_Port.Text = config.Get("port");
            ControlStyleUpdata(picBox_ConnectStatu, Color.Gray);
        }
        private void Frm_TcpClient_FormClosing(object sender, FormClosingEventArgs e)
        {
            tcpTool?.Disconnect();
            tcpTool = null;
        }
        #endregion

        #region 鼠標單擊事件
        private void btn_Connect_Click(object sender, EventArgs e)
        {
            bool isOpen = btn_Connect.Text.Equals("連接") ? true : false;
            if (isOpen)
            {
                tcpTool = new TcpClientTool(tbx_IpAddress.Text, tbx_Port.Text);
                tcpTool.ExecuteMessageChanged += TcpTool_ExecuteMessageCallBack;
                tcpTool.Connect();
            }
            else
            {
                tcpTool.Disconnect();
            }
            if (tcpTool.IsConnected) picBox_ConnectStatu.BackColor = Color.LimeGreen;
            else picBox_ConnectStatu.BackColor = Color.Gray;
            btn_Connect.Text = tcpTool.IsConnected ? "斷開" : "連接";
        }
        private void btn_Send_Click(object sender, EventArgs e)
        {
            if (tcpTool != null)
            {
                tcpTool.Send(rtbx_SendData.Text);
            }
        }
        private void btn_ClearReceiveData_Click(object sender, EventArgs e)
        {
            rtbx_ReceiveData.Text = string.Empty;
        }
        private void btn_ClearSendData_Click(object sender, EventArgs e)
        {
            rtbx_SendData.Text = string.Empty;
        }
        #endregion

        #region 控件圓角方法
        /// <summary>
        /// 控件樣式更新
        /// </summary>
        public void ControlStyleUpdata(Control control)
        {
            GraphicsPath gp = new GraphicsPath();
            gp.AddEllipse(control.ClientRectangle);
            Region region = new Region(gp);
            control.Region = region;
            gp.Dispose();
            region.Dispose();
        }
        /// <summary>
        /// 控件樣式更新
        /// </summary>
        public void ControlStyleUpdata(Control control, Color bcColor)
        {
            control.BackColor = bcColor;
            ControlStyleUpdata(control);
        }
        #endregion
        /// <summary>
        /// 操作消息更新
        /// </summary>
        private void TcpTool_ExecuteMessageCallBack(object sender, string e)
        {
            MessageShow(e);
        }
        /// <summary>
        /// 消息顯示到控件
        /// </summary>
        public void MessageShow(string data)
        {
            rtbx_ReceiveData.Invoke(new Action(() =>
            {
                rtbx_ReceiveData.AppendText($"{DateTime.Now}】{data}{System.Environment.NewLine}");
            }));
        }
    }
}

5. 主窗口模塊-MainForm

功能聚合主窗口界面:

using System;
using System.IO;
using System.Windows.Forms;

namespace JoTcp
{
    public partial class MainForm : Form
    {
        Frm_TcpClient tcpClient;
        Frm_TcpServer tcpServer;
        public MainForm()
        {
            InitializeComponent();
            this.MinimumSize = new System.Drawing.Size(820, 745);

            this.Size = new System.Drawing.Size(820, 745);

            //1197, 189
        }
        /// <summary>
        /// 點擊服務端按鈕,顯示服務端
        /// </summary>
        private void btn_TCPServer_Click(object sender, EventArgs e)
        {
            if (tcpServer == null)
            {
                tcpServer = new Frm_TcpServer();
            }
            panel_Container.Controls.Clear();//移除所有控件

            tcpServer.TopLevel = false;
            tcpServer.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            panel_Container.Width = tcpServer.Width;
            tcpServer.Dock = DockStyle.Fill;
            panel_Container.Controls.Add(tcpServer);
            tcpServer.Show();

        }
        /// <summary>
        /// 點擊客戶端按鈕,顯示客戶端
        /// </summary>
        private void btn_TCPClient_Click(object sender, EventArgs e)
        {
            if (tcpClient == null)
            {
                tcpClient = new Frm_TcpClient();
            }
            panel_Container.Controls.Clear();//移除所有控件

            tcpClient.TopLevel = false;
            tcpClient.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            panel_Container.Width = tcpClient.Width;
            tcpClient.Dock = DockStyle.Fill;
            panel_Container.Controls.Add(tcpClient);
            tcpClient.Show();

        }

        /// <summary>
        /// 窗體加載時,顯示服務端
        /// </summary>
        private void MainForm_Load(object sender, EventArgs e)
        {

            if (tcpServer == null)
            {
                tcpServer = new Frm_TcpServer();
            }
            panel_Container.Controls.Clear();//移除所有控件

            tcpServer.TopLevel = false;
            tcpServer.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            panel_Container.Width = tcpServer.Width;
            tcpServer.Dock = DockStyle.Fill;
            panel_Container.Controls.Add(tcpServer);
            tcpServer.Show();

            // 日志目錄創(chuàng)建
            String directoryPath = "log";
            if (!Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
                //Console.WriteLine("目錄已創(chuàng)建: " + directoryPath);
            }
            else
            {
                //Console.WriteLine("目錄已存在: " + directoryPath);
            }

        }

        /// <summary>
        /// 窗體關閉,關閉服務端、客戶端
        /// </summary>
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            tcpClient?.Close();
            tcpServer?.Close();
        }


        private void server_btn_Click(object sender, EventArgs e)
        {
            if (tcpServer == null)
            {
                tcpServer = new Frm_TcpServer();
            }
            panel_Container.Controls.Clear();//移除所有控件

            tcpServer.TopLevel = false;
            tcpServer.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            panel_Container.Width = tcpServer.Width;
            tcpServer.Dock = DockStyle.Fill;
            panel_Container.Controls.Add(tcpServer);
            tcpServer.Show();
        }

        private void client_btn_Click(object sender, EventArgs e)
        {
            if (tcpClient == null)
            {
                tcpClient = new Frm_TcpClient();
            }
            panel_Container.Controls.Clear();//移除所有控件

            tcpClient.TopLevel = false;
            tcpClient.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            panel_Container.Width = tcpClient.Width;
            tcpClient.Dock = DockStyle.Fill;
            panel_Container.Controls.Add(tcpClient);
            tcpClient.Show();
        }

        private void ServerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            labelTitle.Text = "接推服務端";
            if (tcpServer == null)
            {
                tcpServer = new Frm_TcpServer();
            }
            panel_Container.Controls.Clear();//移除所有控件

            tcpServer.TopLevel = false;
            tcpServer.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            panel_Container.Width = tcpServer.Width;
            tcpServer.Dock = DockStyle.Fill;
            panel_Container.Controls.Add(tcpServer);
            tcpServer.Show();
        }

        private void ClientToolStripMenuItem_Click(object sender, EventArgs e)
        {
            labelTitle.Text = "模擬客戶端";
            if (tcpClient == null)
            {
                tcpClient = new Frm_TcpClient();
            }
            panel_Container.Controls.Clear();//移除所有控件

            tcpClient.TopLevel = false;
            tcpClient.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            panel_Container.Width = tcpClient.Width;
            tcpClient.Dock = DockStyle.Fill;
            panel_Container.Controls.Add(tcpClient);
            tcpClient.Show();
        }

        private void AboutToolStripMenuItem_Click(object sender, EventArgs e)
        { 
                Frm_about dialog = new Frm_about(); // 
                dialog.ShowDialog(); // 使用ShowDialog()方法顯示對話框,這會阻止代碼繼續(xù)執(zhí)行直到對話框關閉
           

        }
    }
}

6. 入庫主程序-Program

using System;
using System.Windows.Forms;

namespace JoTcp
{
    internal static class Program
    {
        /// <summary>
        /// 應用程序的主入口點。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }
}

四、關于配置文件

本程序采用了自定義的INI單層配置方案,在config.ini中直接配置以下參數(shù):

## 配置
ip=127.0.0.1
port=9001
apiurl=https://api.2om.cn/ceshi

五、使用場景 & 實測效果

物聯(lián)網(wǎng)設備測試:和 PLC、傳感器建立 TCP 連接,實時接收設備數(shù)據(jù)并推送到云平臺,驗證設備穩(wěn)定性。

服務端日志轉發(fā):接收 Windows/Linux 服務器的 TCP 日志流,推送到 ELK 等日志分析平臺,無需手動采集。

.NET 項目數(shù)據(jù)上報:本地.NET 程序生成的數(shù)據(jù)通過 TCP 發(fā)送,工具自動轉發(fā)到業(yè)務 API,簡化項目開發(fā)。

實測效果(.NET 4.7 + Windows 10):

  • 數(shù)據(jù)處理能力:每秒 150 + 條 TCP 數(shù)據(jù),API 推送無阻塞
  • 重連穩(wěn)定性:斷網(wǎng)后 5 秒自動重連,恢復后無縫續(xù)傳
  • 推送可靠性:API 臨時不可用時,重試 3 次后仍失敗會記錄日志,避免數(shù)據(jù)丟失

到此這篇關于C#基于TCP/IP實現(xiàn)接收并推送數(shù)據(jù)的小工具的文章就介紹到這了,更多相關C#數(shù)據(jù)接收與推送內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論

乐东| 运城市| 泰州市| 桃园市| 旺苍县| 普陀区| 来宾市| 合作市| 郓城县| 普宁市| 汪清县| 广昌县| 平江县| 田阳县| 南靖县| 昂仁县| 苍南县| 当雄县| 张家港市| 石阡县| 上饶县| 曲阳县| 普兰县| 永泰县| 海原县| 伊川县| 南投市| 周口市| 阿城市| 当阳市| 黎城县| 潢川县| 临泽县| 荆门市| 安岳县| 昆山市| 许昌市| 凭祥市| 泸西县| 平原县| 湖南省|