C# 三种方式实现Socket数据接收(经典)

  • A+
所属分类:.NET技术
摘要

Stream.Read 方法当在派生类中重写时,从当前流读取字节序列,并将此流中的位置提升读取的字节数。

Stream.Read 方法

当在派生类中重写时,从当前流读取字节序列,并将此流中的位置提升读取的字节数。

语法

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

参数

  • buffer: 字节数组。此方法返回时,该缓冲区包含指定的字符数组,该数组的 offset 和 (offset + count -1) 之间的值由从当前源中读取的字节替换。

  • offsetbuffer 中的从零开始的字节偏移量,从此处开始存储从当前流中读取的数据。

  • 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),数据接收正常

以下分别采用三种方式实现了数据的正常接收,代码如下:

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数据接收(经典)

 

----------------------------------------------------

以上就是本节的全部内容,如果感觉有用,请多多的点击在看和分享,需要进技术交流群的,请加小编微信zls20210502,切记备注 进群