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),数据接收正常。
以下分别采用三种方式实现了数据的正常接收,代码如下:
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数据接收(经典)的更多相关文章
- PHP中数据类型转换的三种方式
PHP中数据类型转换的三种方式 PHP的数据类型转换属于强制转换,允许转换的PHP数据类型有: 1.(int).(integer):转换成整形2.(float).(double).(real):转换成 ...
- 三种方式实现观察者模式 及 Spring中的事件编程模型
观察者模式可以说是众多设计模式中,最容易理解的设计模式之一了,观察者模式在Spring中也随处可见,面试的时候,面试官可能会问,嘿,你既然读过Spring源码,那你说说Spring中运用的设计模式吧, ...
- 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 ...
- python 全栈开发,Day94(Promise,箭头函数,Django REST framework,生成json数据三种方式,serializers,Postman使用,外部python脚本调用django)
昨日内容回顾 1. 内容回顾 1. VueX VueX分三部分 1. state 2. mutations 3. actions 存放数据 修改数据的唯一方式 异步操作 修改state中数据的步骤: ...
- Struts2(四.注册时检查用户名是否存在及Action获取数据的三种方式)
一.功能 1.用户注册页面 <%@ page language="java" contentType="text/html; charset=UTF-8" ...
- Ajax上传数据和上传文件(三种方式)
Ajax向后端发送数据可以有三种方式:原生Ajax方式,jQuery Ajax方式,iframe+form 方式(伪造Ajax方式) <!DOCTYPE html> <html la ...
- iOS --- UIWebView的加载本地数据的三种方式
UIWebView是IOS内置的浏览器,可以浏览网页,打开文档 html/htm pdf docx txt等格式的文件. safari浏览器就是通过UIWebView做的. 服务器将MIM ...
- C#批量插入数据到Sqlserver中的三种方式
本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生 成 ...
- ios网络学习------4 UIWebView的加载本地数据的三种方式
ios网络学习------4 UIWebView的加载本地数据的三种方式 分类: IOS2014-06-27 12:56 959人阅读 评论(0) 收藏 举报 UIWebView是IOS内置的浏览器, ...
随机推荐
- 真实机中安装CentOS
前言 最近在b站上看了兄弟连老师的Linux教程,非常适合入门:https://www.bilibili.com/video/BV1mW411i7Qf 看完后就自己来试着玩下,正好手上有台空闲的电脑就 ...
- canvas二次贝塞尔&三次贝塞尔操作实例
Canvas Quadratic Curve Example canvas = document.getElementById("canvas"); ctx = canvas.ge ...
- IDEA中的Git操作,看这一篇就够了!
大家在使用Git时,都会选择一种Git客户端,在IDEA中内置了这种客户端,可以让你不需要使用Git命令就可以方便地进行操作,本文将讲述IDEA中的一些常用Git操作. 环境准备 使用前需要安装一个远 ...
- mybatis第一个程序随笔
今天继续学习了解如何写一个mybatis程序 创建了Dao层 1.1 创建一个UserDao接口 1.2 创建UserMapper.xml文件 在mybaits中文手册查找配置信息 <?xml ...
- ucosii操作系统内核源码学习第一篇
根据书本理论介绍以及实际看内核源代码得出: 1. 操作系统默认定义了64个TCB块(为全局变量,编译时候以及分配了,创建一个任务就使用一个,删除一个任务就归还一个)(为什么最大只支持64个任务呢,我们 ...
- 记一次线上问题 → 对 MySQL 的 ON UPDATE CURRENT_TIMESTAMP 的片面认知
开心一刻 老婆痛经,躺在沙发上,两岁的女儿看着她问道 女儿:妈妈,你怎么了 老婆:妈妈肚子痛 女儿:哦,妈妈你头疼 老婆:不是头疼,妈妈是肚子疼 女儿用她的不锈钢饭碗砸向老婆的额头,说道:妈妈,你哪里 ...
- noip模拟测试18
打开比赛第一眼--超级树? 点开--原题 百感交集-- 欣喜于发现是半年前做过两遍的原题 紧张于如果A不了比较尴尬 绝望于发现根本不会做了 瞟了一眼t1,瞅了一眼t2,嗯--开始搞t3 10分钟打完暴 ...
- IT人计算机网络浅析
LAN: 局域网 local Area Network WAN: 广域网 Wide Area Network WAN = LAN +LAN+....+LAN 多个LAN 组成 WAN OSI 七层协议 ...
- JS012. 变量存储含class、id等其他属性的标签元素(动态渲染DOM结点)
项目中有一处源码需要用变量存储html标签,包含类名和其他一些属性,再动态地将其渲染到页面上. 看下普通的存储方式: initHtml: function () { var me = this; // ...
- CSS002. 字体穿透蒙层(用img设置字体的color)
之前在逛Apple Store时看到了下面的UI: 交互图标非常圆滑上手也很舒服,虽然背景底色本就是白底,但是只依赖css能不能使 "+" 穿透背景看到底色 ? 大致思路如下: ...