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("指令发送成功");
}
}
}

  

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

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

C# 三种方式实现Socket数据接收(经典)的更多相关文章

  1. PHP中数据类型转换的三种方式

    PHP中数据类型转换的三种方式 PHP的数据类型转换属于强制转换,允许转换的PHP数据类型有: 1.(int).(integer):转换成整形2.(float).(double).(real):转换成 ...

  2. 三种方式实现观察者模式 及 Spring中的事件编程模型

    观察者模式可以说是众多设计模式中,最容易理解的设计模式之一了,观察者模式在Spring中也随处可见,面试的时候,面试官可能会问,嘿,你既然读过Spring源码,那你说说Spring中运用的设计模式吧, ...

  3. Linux就这个范儿 第15章 七种武器 linux 同步IO: sync、fsync与fdatasync Linux中的内存大页面huge page/large page David Cutler Linux读写内存数据的三种方式

    Linux就这个范儿 第15章 七种武器  linux 同步IO: sync.fsync与fdatasync   Linux中的内存大页面huge page/large page  David Cut ...

  4. python 全栈开发,Day94(Promise,箭头函数,Django REST framework,生成json数据三种方式,serializers,Postman使用,外部python脚本调用django)

    昨日内容回顾 1. 内容回顾 1. VueX VueX分三部分 1. state 2. mutations 3. actions 存放数据 修改数据的唯一方式 异步操作 修改state中数据的步骤: ...

  5. Struts2(四.注册时检查用户名是否存在及Action获取数据的三种方式)

    一.功能 1.用户注册页面 <%@ page language="java" contentType="text/html; charset=UTF-8" ...

  6. Ajax上传数据和上传文件(三种方式)

    Ajax向后端发送数据可以有三种方式:原生Ajax方式,jQuery Ajax方式,iframe+form 方式(伪造Ajax方式) <!DOCTYPE html> <html la ...

  7. iOS --- UIWebView的加载本地数据的三种方式

    UIWebView是IOS内置的浏览器,可以浏览网页,打开文档  html/htm  pdf   docx  txt等格式的文件.  safari浏览器就是通过UIWebView做的. 服务器将MIM ...

  8. C#批量插入数据到Sqlserver中的三种方式

    本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生 成 ...

  9. ios网络学习------4 UIWebView的加载本地数据的三种方式

    ios网络学习------4 UIWebView的加载本地数据的三种方式 分类: IOS2014-06-27 12:56 959人阅读 评论(0) 收藏 举报 UIWebView是IOS内置的浏览器, ...

随机推荐

  1. 恶意软件开发——shellcode执行的几种常见方式

    一.什么是shellcode? shellcode是一小段代码,用于利用软件漏洞作为有效载荷.它之所以被称为"shellcode",是因为它通常启动一个命令shell,攻击者可以从 ...

  2. Windows-MacOSX-Ubuntu·不同平台文件互传文件共享

    时间:2018-11-23 整理:byzqy 标题:Mac下的virtual box 安装的Ubuntu虚拟机互传文件问题 地址:https://blog.csdn.net/qq_20044689/a ...

  3. Ubuntu16.04 Linux 下无痛安装、配置Gogs

    本文在Win7+VMware的ubuntu 16.04中测试,安装Gogs,Install from binary. 准备工作: sudo apt-get install git sudo addus ...

  4. Python3-sqlalchemy-orm 分组统计

    #-*-coding:utf-8-*- #__author__ = "logan.xu" import sqlalchemy from sqlalchemy import crea ...

  5. Mysql - You can't specify target table '表名' for update in FROM clause 错误解决办法

    背景 在MySQL中,写SQL语句的时候 ,可能会遇到 You can't specify target table '表名' for update in FROM clause 这样的错误 错误含义 ...

  6. Identity用户管理入门三(注册用户)

    用户注册主要有2个方法,1.密码加密 2.用户注册 3.ASP.NET Core Identity 使用密码策略.锁定和 cookie 配置等设置的默认值. 可以在类中重写这些设置 Startup(官 ...

  7. jdbcTemplate快速入门

    一. c3p0和dbcp区别 二.导包 hibernate通过映射自动创建表: 三.代码实现

  8. hadoop集群搭建详细教程

    本文针对hadoop集群的搭建过程给予一个详细的介绍. 参考视频教程:https://www.bilibili.com/video/BV1tz4y127hX?p=1&share_medium= ...

  9. STM32CbueIDE 体验

    STM32CbueIDE 体验 下载安装 官网下载链接:https://www.st.com/zh/development-tools/stm32cubeide.html. 软件启动时会令设置工作目录 ...

  10. 手机访问pc网站自动跳转手机端网站PHP代码

    $agent = $_SERVER['HTTP_USER_AGENT']; if(strpos($agent,"comFront") strpos($agent,"iPh ...