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

C#實(shí)現(xiàn)Socket數(shù)據(jù)接收的三種經(jīng)典方式

 更新時(shí)間:2025年08月15日 10:15:15   作者:小碼編匠  
本文將深入探討 C# 中實(shí)現(xiàn) Socket 數(shù)據(jù)接收的三種經(jīng)典方式,結(jié)合真實(shí)案例分析常見(jiàn)問(wèn)題,并提供優(yōu)化后的完整代碼示例,希望對(duì)大家有一定的幫助

前言

在工業(yè)自動(dòng)化、物聯(lián)網(wǎng)(IoT)和網(wǎng)絡(luò)通信等領(lǐng)域,Socket 編程是實(shí)現(xiàn)設(shè)備間數(shù)據(jù)交互的核心技術(shù)。C# 作為 .NET 平臺(tái)的主要開(kāi)發(fā)語(yǔ)言,提供強(qiáng)大的網(wǎng)絡(luò)編程支持。然而,在實(shí)際開(kāi)發(fā)中,很多開(kāi)發(fā)在使用 Socket.Receive 方法接收數(shù)據(jù)時(shí),常常遇到數(shù)據(jù)丟失、接收延遲、性能瓶頸等問(wèn)題。

本文將深入探討 C# 中實(shí)現(xiàn) Socket 數(shù)據(jù)接收的三種經(jīng)典方式,結(jié)合真實(shí)案例分析常見(jiàn)問(wèn)題,并提供優(yōu)化后的完整代碼示例,幫助大家開(kāi)發(fā)穩(wěn)定、高效的網(wǎng)絡(luò)通信系統(tǒng)。

問(wèn)題背景

在傳統(tǒng)的 Socket 數(shù)據(jù)接收方式中,通常采用如下代碼:

int recv;//定義接收數(shù)據(jù)長(zhǎng)度變量
IPEndPoint ipEnd = new IPEndPoint(IPAddress.Parse(textBox1.Text), int.Parse(textBox2.Text));
//接收端所監(jiān)聽(tīng)的接口,ip也可以用IPAddress.Any
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//初始化一個(gè)Socket對(duì)象
socket.Bind(ipEnd);
//綁定套接字到一個(gè)IP地址和一個(gè)端口上(bind());
socket.Listen(10);
while (true)
{
    byte[] data = new byte[1024];//對(duì)data清零
    Socket clientSocket = socket.Accept(); 
    //一旦接受連接,創(chuàng)建一個(gè)客戶端
    recv = clientSocket.Receive(data);
    if (recv == 0) 
    //如果收到的數(shù)據(jù)長(zhǎng)度小于0,則退出
        break;
    string stringData = "0x" + BitConverter.ToString(data).Replace("-", " 0x").ToLower();
    
    this.Invoke((EventHandler)delegate
    {
        richTextBox1.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss")  + stringData + "\n";
    });
}

這種寫(xiě)法在簡(jiǎn)單場(chǎng)景下看似可行,但在處理高頻、小包數(shù)據(jù)(如金屬門(mén)每10秒發(fā)送一次數(shù)據(jù))時(shí),會(huì)出現(xiàn)嚴(yán)重的數(shù)據(jù)積壓和延遲——原本應(yīng)60秒接收6組數(shù)據(jù),卻可能60秒才收到一組,導(dǎo)致數(shù)據(jù)丟失。

根本原因在于:Receive 方法被放在 Accept 之后的單次調(diào)用中,未能持續(xù)監(jiān)聽(tīng)和接收數(shù)據(jù)流。

三種高效的數(shù)據(jù)接收方式

為解決上述問(wèn)題,以下介紹三種經(jīng)過(guò)驗(yàn)證的 C# Socket 數(shù)據(jù)接收方案。

方式一:基于NetworkStream.Read的持續(xù)監(jiān)聽(tīng)

使用 TcpClientNetworkStream,通過(guò) Stream.Read 方法實(shí)現(xiàn)阻塞式持續(xù)讀取。

private void BGWorker_DoWork()
{
    var serverIPEndPoint = new IPEndPoint(IPAddress.Parse("192.168.1.99"), 8234); // 當(dāng)前服務(wù)器使用的ip和端口
    TcpListener tcpListener = new TcpListener(serverIPEndPoint);
    tcpListener.Start();
    Console.WriteLine("服務(wù)端已啟用......"); // 阻塞線程的執(zhí)行,直到一個(gè)客戶端連接
    tcpClient = tcpListener.AcceptTcpClient();
    Console.WriteLine("已連接.");
    stream = tcpClient.GetStream();          // 創(chuàng)建用于發(fā)送和接受數(shù)據(jù)的NetworkStream

    var t1 = new Thread(ReceiveMsg);
    t1.IsBackground = true;
    t1.Start();
}

void ReceiveMsg()
{
    byte[] buffer = new byte[1024]; // 預(yù)設(shè)最大接受1024個(gè)字節(jié)長(zhǎng)度,可修改
    int count = 0;
    try
    {
        while ((count = stream.Read(buffer, 0, buffer.Length)) != 0)
        {
            string stringData = "0x" + BitConverter.ToString(buffer, 0, count).Replace("-", " 0x").ToLower();
            Console.WriteLine($"{tcpClient.Client.LocalEndPoint.ToString()}:{DateTime.Now.ToString("yy-MM-dd hh:mm:ss -*- ") + stringData + "\n"}");
            this.Invoke((EventHandler)delegate
            {
                richTextBox1.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss -*- ") + stringData + "\n";
            });
        }
    }
    catch(Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}

優(yōu)點(diǎn):代碼簡(jiǎn)潔,NetworkStream.Read 自動(dòng)處理流的持續(xù)讀取。

適用場(chǎng)景:?jiǎn)慰蛻舳送ㄐ?,如設(shè)備與上位機(jī)一對(duì)一連接。

方式二:多線程處理多個(gè)客戶端連接

為每個(gè)客戶端連接創(chuàng)建獨(dú)立線程,確保接收不阻塞主線程。

private void BGWorker_DoWork1()
{
    int recv;
    IPEndPoint ipEnd = new IPEndPoint(IPAddress.Parse(textBox1.Text), int.Parse(textBox2.Text));
    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    socket.Bind(ipEnd);
    socket.Listen(10);

    Thread thread = new Thread(Listen);
    thread.IsBackground = true;
    thread.Start(socket);
}

void Listen(object o)
{
    try
    {
        Socket socketWatch = o as Socket;
        while (true)
        {
            socketSend = socketWatch.Accept();
            Thread r_thread = new Thread(Received);
            r_thread.IsBackground = true;
            r_thread.Start(socketSend);
        }
    }
    catch { }
}

void Received(object o)
{
    try
    {
        Socket socketSend = o as Socket;
        while (true)
        {
            byte[] buffer = new byte[1024 * 1024 * 3];
            int len = socketSend.Receive(buffer);
            if (len == 0)
            {
                break;
            }
            string stringData = "0x" + BitConverter.ToString(buffer, 0, len).Replace("-", " 0x").ToLower();
            this.Invoke((EventHandler)delegate
            {
                richTextBox1.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss -*- ") + stringData + "\n";
            });
        }
    }
    catch { }
}

優(yōu)點(diǎn):支持多客戶端并發(fā)連接,接收獨(dú)立,互不干擾。

適用場(chǎng)景:多設(shè)備接入的服務(wù)器端程序。

方式三:Task + Background Thread 實(shí)現(xiàn)異步接收

結(jié)合 Task.Run 和后臺(tái)線程,實(shí)現(xiàn)輕量級(jí)異步接收,避免線程資源浪費(fèi)。

private void BGWorker_DoWork2()
{
    int recv;
    IPEndPoint ipEnd = new IPEndPoint(IPAddress.Parse(textBox1.Text), int.Parse(textBox2.Text));
    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    socket.Bind(ipEnd);
    socket.Listen(10);
    new Thread(delegate ()
    {
        Socket clientSocket = null;
        while (true)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();

            clientSocket = socket.Accept();

            Task.Run(() =>
            {
                while (true)
                {
                    byte[] data = new byte[50];
                    recv = clientSocket.Receive(data, 0, data.Length, SocketFlags.None);
                    string stringData = "0x" + BitConverter.ToString(data, 0, recv).Replace("-", " 0x").ToLower();

                    this.Invoke((EventHandler)delegate
                    {
                        richTextBox1.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss -*- ") + stringData + "\n";
                    });
                    sw.Stop();
                    long times = sw.ElapsedMilliseconds;
                    this.Invoke((EventHandler)delegate
                    {
                        richTextBox1.Text += "執(zhí)行查詢總共使用了" + times + "毫秒" + "\n";
                    });
                }
            });
        }
    })
    { IsBackground = true }.Start();
}

優(yōu)點(diǎn):異步非阻塞,資源利用率高,適合高并發(fā)場(chǎng)景。

適用場(chǎng)景:需要高性能、低延遲的工業(yè)通信系統(tǒng)。

總結(jié)

本文通過(guò)一個(gè)真實(shí)的數(shù)據(jù)接收延遲案例,揭示了傳統(tǒng) Socket.Receive 使用方式的局限性,并提供了三種經(jīng)過(guò)實(shí)踐驗(yàn)證的優(yōu)化方案:

1、NetworkStream.Read:適合簡(jiǎn)單、穩(wěn)定的單連接場(chǎng)景,代碼簡(jiǎn)潔。

2、多線程 Accept + Receive:適合多客戶端并發(fā)接入,結(jié)構(gòu)清晰。

3、Task + Thread 異步模式:適合高性能、高并發(fā)系統(tǒng),資源利用更優(yōu)。

選擇哪種方式,取決于具體的應(yīng)用場(chǎng)景和性能需求。

無(wú)論哪種方式,核心原則是:必須將數(shù)據(jù)接收邏輯置于持續(xù)監(jiān)聽(tīng)的循環(huán)中,避免一次性調(diào)用導(dǎo)致的數(shù)據(jù)丟失。

另外,結(jié)合 Stopwatch 進(jìn)行性能監(jiān)控、使用 Invoke 安全更新 UI、合理設(shè)置緩沖區(qū)大小,都是構(gòu)建穩(wěn)定 Socket 通信系統(tǒng)的關(guān)鍵。

到此這篇關(guān)于C#實(shí)現(xiàn)Socket數(shù)據(jù)接收的三種經(jīng)典方式的文章就介紹到這了,更多相關(guān)C# Socket數(shù)據(jù)接收內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

平乐县| 轮台县| 德惠市| 民县| 喜德县| 兰溪市| 四子王旗| 山东省| 常熟市| 久治县| 临沂市| 孝昌县| 安丘市| 元谋县| 普定县| 竹溪县| 睢宁县| 揭西县| 项城市| 阆中市| 固始县| 马龙县| 五河县| 南开区| 嵊泗县| 中西区| 甘泉县| 吉安市| 松滋市| 光山县| 苍梧县| 富民县| 晴隆县| 古蔺县| 常德市| 齐齐哈尔市| 壶关县| 博客| 元谋县| 武城县| 武邑县|