C# 三種方式實現Socket數據接收

Stream.Read 方法

當在派生類中重寫時,從當前流讀取字節序列,並將此流中的位置提升讀取的字節數。

語法:

public abstract int Read(byte[] buffer, int offset, int count)

參數:

buffer : 字節數組。此方法返回時,該緩沖區包含指定的字符數組,該數組的  offset 和 ( offset +  count -1) 之間的值由從當前源中讀取的字節替換。

offset buffer 中的從零開始的字節偏移量,從此處開始存儲從當前流中讀取的數據。

count : 要從當前流中最多讀取的字節數。

返回值:

讀入緩沖區中的總字節數。如果當前可用的字節數沒有請求的字節數那麼多,則總字節數可能小於請求的字節數,或者如果已到達流的末尾,則為零 (0)。

備註:

此方法的實現從當前流中讀取最多的 count 個字節,並將它們存儲在從  offset 開始的  buffer 中。流中的當前位置提升已讀取的字節數;但是,如果出現異常,流中的當前位置保持不變。實現返回已讀取的字節數。僅當位置當前位於流的末尾時,返回值才為零。如果沒有任何可用的數據,該實現將一直阻塞到至少有一個字節的數據可讀為止。僅當流中不再有其他的數據,而且也不再需要更多的數據(如已關閉的套接字或文件尾)時, Read 才返回 0。 即使尚未到達流的末尾,實現仍可以隨意返回少於所請求的字節。

之前一般采用如下方式進行數據接收:

int recv;//定義接收數據長度變量
            IPEndPoint ipEnd = new IPEndPoint(IPAddress.Parse(textBox1.Text), int.Parse(textBox2.Text));//接收端所監聽的接口,ip也可以用IPAddress.Any
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//初始化一個Socket對象
            socket.Bind(ipEnd);//綁定套接字到一個IP地址和一個端口上(bind());
            socket.Listen(10);
            while (true)
            {
                byte[] data = new byte[1024];//對data清零
                Socket clientSocket = socket.Accept(); //一旦接受連接,創建一個客戶端
                recv = clientSocket.Receive(data);
                if (recv == 0) //如果收到的數據長度小於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";
                });
            }


之前用的時候沒發現什麼問題,但是今天在測試金屬門數據接收的時候發現會丟數據,金屬門每隔十秒給我一次數據,用上面這個差不多60秒才能收到一組數據,針對以上問題,做瞭如下修改:

將數據接收放到 while (true)

將數據接收放到 while (true),數據接收正常

以下分別采用三種方式實現瞭數據的正常接收,代碼如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MetalGate
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }
        private BackgroundWorker demoBGWorker = new BackgroundWorker();
        static TcpClient tcpClient;
        static NetworkStream stream;
        private void MainForm_Load(object sender, EventArgs e)
        {
            textBox1.Text = "192.168.1.99";
            textBox2.Text = "8234";

        }
        //private void BGWorker_DoWork(object sender, DoWorkEventArgs e)
         private void BGWorker_DoWork()
        {
            
            var serverIPEndPoint = new IPEndPoint(IPAddress.Parse("192.168.1.99"), 8234); // 當前服務器使用的ip和端口
            TcpListener tcpListener = new TcpListener(serverIPEndPoint);
            tcpListener.Start();
            Console.WriteLine("服務端已啟用......"); // 阻塞線程的執行,直到一個客戶端連接
            tcpClient = tcpListener.AcceptTcpClient();
            Console.WriteLine("已連接.");
            stream = tcpClient.GetStream();          // 創建用於發送和接受數據的NetworkStream


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

        }
        private void BGWorker_DoWork1()
        {
            //在這裡執行耗時的運算。
            int recv;//定義接收數據長度變量
            IPEndPoint ipEnd = new IPEndPoint(IPAddress.Parse(textBox1.Text), int.Parse(textBox2.Text));//接收端所監聽的接口,ip也可以用IPAddress.Any
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//初始化一個Socket對象
            socket.Bind(ipEnd);//綁定套接字到一個IP地址和一個端口上(bind());
            socket.Listen(10);

            //創建監聽線程
             Thread thread = new Thread(Listen);
             thread.IsBackground = true;
             thread.Start(socket);

          
        }
         /// <summary>
        /// 等待客戶端的連接 並且創建與之通信的Socket
        /// </summary>
        Socket socketSend;
        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 { }
        }
        /// <summary>
         /// 服務器端不停的接收客戶端發來的消息
         /// </summary>
         /// <param name="o"></param>
         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 str = Encoding.UTF8.GetString(buffer, 0, len);
                    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 { }
         }

        private void BGWorker_DoWork2()
        {
            int recv;//定義接收數據長度變量
            IPEndPoint ipEnd = new IPEndPoint(IPAddress.Parse(textBox1.Text), int.Parse(textBox2.Text));//接收端所監聽的接口,ip也可以用IPAddress.Any
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//初始化一個Socket對象
            socket.Bind(ipEnd);//綁定套接字到一個IP地址和一個端口上(bind());
            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];//對data清零
                            recv = clientSocket.Receive(data, 0, data.Length, SocketFlags.None);
                            //if (recv == 0) //如果收到的數據長度小於0,則退出
                            //    break;
                            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 += "執行查詢總共使用瞭" + times + "毫秒" + "\n";
                            });
                        }
                    });
                }
            })
            { IsBackground = true }.Start();
        }

        void ReceiveMsg()
        {
            byte[] buffer = new byte[1024]; // 預設最大接受1024個字節長度,可修改
            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);
            }
            
        }

            private void SendData(IPAddress remoteIP, int Port, byte[] bits)
        {
            //實例化socket               
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ipep = new IPEndPoint(remoteIP, Port);
            socket.Connect(ipep);
            //socket.Send(bits, 8, SocketFlags.None);
            socket.Send(bits);
            socket.Close();
        }

        private void btnListen_Click(object sender, EventArgs e)
        {
            //demoBGWorker.DoWork += BGWorker_DoWork;
            //demoBGWorker.RunWorkerAsync();
            //Task.Run(() =>
           // {
                BGWorker_DoWork2();
            //});
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            byte[] order = new byte[8];
            order = new byte[] { 0x80, 0x04, 0x00, 0x7F };
            SendData(IPAddress.Parse("192.168.1.100"), int.Parse("49558"), order);
            MessageBox.Show("指令發送成功");
        }
    }
}

到此這篇關於C# 三種方式實現Socket數據接收的文章就介紹到這瞭,更多相關C# 實現Socket數據接收內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: