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!