C#通过Socket读取大量数据
在C#中经常会用到Socket去接收和发送数据,而且也是非常方便的,有时候我们会向服务端去请求数据,如果返回的数据量很大,比如超过10M甚至是更多,那么该怎样去接收数据呢?下面以一个在项目中用到的实例去分析和解释这个问题,先看看下面的这段代码?
/// <summary>
/// 返回摄像头信息
/// </summary>
private void RcvCameraInfos(object obj)
{
string sourceIp = System.Configuration.ConfigurationSettings.AppSettings["SourceIP"].ToString();
string sourcePort = System.Configuration.ConfigurationSettings.AppSettings["SourcePort"].ToString(); Socket mysocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(sourceIp), int.Parse(sourcePort));
mysocket.Connect(ipEndPoint); DateTime start = DateTime.Now; string s = "<?xml version=\"1.0\" ?>";
s += "<info name=\"getcameracodematrixtable\"/>\0";
byte[] buffer = System.Text.ASCIIEncoding.GetEncoding("GB2312").GetBytes(s);
mysocket.Send(buffer); Action<string> OnCamraInfoRcvCompleted = obj as Action<string>; int recvsize = 0;
int dataSize = 2048 * 1000;
int ret = 0;
byte[] datas = new byte[dataSize];
SortedList<string, string[]> cameraDictionnary = new SortedList<string, string[]>();
string xmlString = "";
while (recvsize < dataSize)
{
ret = mysocket.Receive(datas, recvsize, dataSize - recvsize, SocketFlags.None);
if (ret <= 0)
{
break;
}
recvsize += ret;
if (datas[recvsize - 1] == 0)
{
break;
}
if (recvsize >= dataSize)
{
byte[] buff2 = new byte[dataSize + 1024];
datas.CopyTo(buff2,0);
datas = buff2;
dataSize += 1024;
}
}
xmlString = System.Text.ASCIIEncoding.GetEncoding("GB2312").GetString(datas, 0, recvsize - 1);
DateTime end = DateTime.Now;
TimeSpan span = end - start;
System.Windows.MessageBox.Show("总共花费时间:"+span.TotalSeconds.ToString()+"秒");
this._videoSourceXmlString = xmlString;
if (cameraDictionnary != null)
{
if (OnCamraInfoRcvCompleted != null) OnCamraInfoRcvCompleted(xmlString);
}
}
上述这段代码的核心是在While循环里面,我们首先接收的BufferSize,这里我们定义2048*1000个字节的大小,ret = mysocket.Receive(datas, recvsize, dataSize - recvsize, SocketFlags.None);通过Socket的这个同步方法来进行接收,datas是我们接收数据的Byte数组,recvsize是当前接收的字节起点(offset),dataSize-recvsize是接收的缓冲区大小,在这个While循环里面,只要是recvsize < dataSize就会不停的去接收数据,当然如果数据量很大的话总有一个时刻recvsize >= dataSize,这个时候我怎就需要增加dataSize了,这里我们去动态增加1KB的大小,通过这样一个边界控制我们就能够去准确获取所有的数据了......
当然这种方式接收数据的缺点就是通过同步的方式,如果接收的数据太多的话,那么花费的时间可能就过长了,特别是在更新UI界面的时候,需要采用异步非阻塞的Socket来接收数据了,或者单独来开一个线程来进行数据接收,然后通过Application.Current.Dispatcher.BeginInvoke的方式来更新到UI上面,不然界面就会卡死,这个需要我们去认真分析......
另外一个当我们这样接收数据然后存入XML文件时,可能XML数据都是连在一起并不能主动换行,这个可以通过下面的方式来解决。
private void SaveCurrentInfoToXML(string recevInfo)
{
string filePath=System.AppDomain.CurrentDomain.BaseDirectory+"CameraInfo.xml";
XmlDocument xd = new XmlDocument();
if (File.Exists(filePath))
{
xd.Load(filePath);
}
else
{
XmlDeclaration xmlDec;
XmlElement xmlEle;
xmlDec = xd.CreateXmlDeclaration("1.0","UTF-8",null);
xd.AppendChild(xmlDec);
xmlEle = xd.CreateElement("Info");
xd.AppendChild(xmlEle);
}
xd.LoadXml(recevInfo);
XmlTextWriter xtw = new XmlTextWriter(filePath, Encoding.UTF8);
xtw.Formatting = Formatting.Indented;
xd.Save(xtw); }
这里我们接收到XML数据后,通过XmlTextWriter写入到XML文件中时,需要设置缩进格式:xtw.Formatting = Formatting.Indented;这样写入数据时数据就会完整,并且处于对齐方式。
C#通过Socket读取大量数据的更多相关文章
- 云计算之路-阿里云上:原来“黑色0.1秒”发生在socket读取数据时
在昨天的博文(云计算之路-阿里云上:读取缓存时的“黑色0.1秒”)中我们犯了一个很低级的错误——把13ms算成了130ms(感谢陈硕发现这个错误!),从而对问题的原因作出了错误的推断,望大家谅解! 从 ...
- Android笔记:Socket客户端收发数据
client.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" and ...
- 2、 Spark Streaming方式从socket中获取数据进行简单单词统计
Spark 1.5.2 Spark Streaming 学习笔记和编程练习 Overview 概述 Spark Streaming is an extension of the core Spark ...
- C#读取Modbus数据
最近在做采集的一些任务所以学了一下Modbus通信,学了好几天昨天终于把大概弄明白了,其实简单来说就是客户端向设备发送一个请求报文请求数据,服务器端根据请求报文向客户端端回发一个报文,客户端在接收到响 ...
- java的poi技术读取Excel数据到MySQL
这篇blog是介绍java中的poi技术读取Excel数据,然后保存到MySQL数据中. 你也可以在 : java的poi技术读取和导入Excel了解到写入Excel的方法信息 使用JXL技术可以在 ...
- Hive读取外表数据时跳过文件行首和行尾
作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 有时候用hive读取外表数据时,比如csv这种类型的,需要跳过行首或者行尾一些和数据无关的或者自 ...
- 读取数据库数据,并将数据整合成3D饼图在jsp中显示
首先我将生成饼图的方法独立写成一个PieChar.java类,详细代码如下:(数据库需要自己建,如有需要的话) import java.io.IOException; import java.sql. ...
- C# TCP socket发送大数据包时,接收端和发送端数据不一致 服务端接收Receive不完全
简单的c# TCP通讯(TcpListener) C# 的TCP Socket (同步方式) C# 的TCP Socket (异步方式) C# 的tcp Socket设置自定义超时时间 C# TCP ...
- .NET读取Excel数据,提示错误:未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序
解决.NET读取Excel数据时,提示错误:未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序的操作: 1. 检查本机是否安装Office Access,如果未安装去去h ...
随机推荐
- Python写代码的用法建议
1.Mutable and immutable types Python有两种内置或用户定义的类型 可变类型是允许就地修改内容的类型.典型的可变列表是列表和词典:所有列表都有变异方法,如 list.a ...
- ActiveMQ后台使用
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/nangeali/article/details/81514517默认地址 http://192.16 ...
- DeeplabV3+ 在自己环境下跑出现的错误
1. no module named 'deeplab' 解决办法:把 models/research 和 models/research/slim 加到环境变量path中不管用,需要在 cmd 中运 ...
- zabbix API应用
1.模拟登录 curl -i -X POST -H 'Content-Type:application/json' -d '{"jsonrpc":"2.0",& ...
- Clustering[Spectral Clustering]
0. 背景 谱聚类在2007年前后十分流行,因为它可以快速的通过标准的线性代数库来实现,且十分优于传统的聚类算法,如k-mean等. 至于在任何介绍谱聚类的算法原理上,随便翻开一个博客,都会有较为详细 ...
- 狄利克雷卷积&莫比乌斯反演总结
狄利克雷卷积&莫比乌斯反演总结 Prepare 1.\([P]\)表示当\(P\)为真时\([P]\)为\(1\),否则为\(0\). 2.\(a|b\)指\(b\)被\(a\)整除. 3.一 ...
- 从源码看Spring Security之采坑笔记(Spring Boot篇)
一:唠嗑 鼓捣了两天的Spring Security,踩了不少坑.如果你在学Spring Security,恰好又是使用的Spring Boot,那么给我点个赞吧!这篇博客将会让你了解Spring S ...
- 【Java并发.6】结构化并发应用程序
6.1 在线程中执行任务 应用程序提供商希望程序支持尽可能多的用户,从而降低每个用户的服务成本,而用户则希望获得尽可能快的响应.大多数服务器应用程序都提供了一种自然的任务边界选择方式:以独立的客户请求 ...
- 编剧小记 — Contour
前言 Contour 是一款比较优秀的编剧辅助软件,按理说这篇文章应该归类到mac小记中,但其操作非常简单,基本上以写作提示为主.只怪所有提示都是英语,而且很多,每次使用打开 Contour 个别单词 ...
- 失物找寻APP软件需求规格说明书——第三次团队作业
⭐对于软件需求规格说明书的理解 在没写这份软件需求规格说明书的时候我们组成员都不是很理解它的必要性,当然,写完之后才知道它的作用. 软件需求说明书的存在是为了使用户和软件开发者双方对该软件的初始规定有 ...