在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读取大量数据的更多相关文章

  1. 云计算之路-阿里云上:原来“黑色0.1秒”发生在socket读取数据时

    在昨天的博文(云计算之路-阿里云上:读取缓存时的“黑色0.1秒”)中我们犯了一个很低级的错误——把13ms算成了130ms(感谢陈硕发现这个错误!),从而对问题的原因作出了错误的推断,望大家谅解! 从 ...

  2. Android笔记:Socket客户端收发数据

    client.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" and ...

  3. 2、 Spark Streaming方式从socket中获取数据进行简单单词统计

    Spark 1.5.2 Spark Streaming 学习笔记和编程练习 Overview 概述 Spark Streaming is an extension of the core Spark ...

  4. C#读取Modbus数据

    最近在做采集的一些任务所以学了一下Modbus通信,学了好几天昨天终于把大概弄明白了,其实简单来说就是客户端向设备发送一个请求报文请求数据,服务器端根据请求报文向客户端端回发一个报文,客户端在接收到响 ...

  5. java的poi技术读取Excel数据到MySQL

    这篇blog是介绍java中的poi技术读取Excel数据,然后保存到MySQL数据中. 你也可以在 : java的poi技术读取和导入Excel了解到写入Excel的方法信息 使用JXL技术可以在 ...

  6. Hive读取外表数据时跳过文件行首和行尾

    作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 有时候用hive读取外表数据时,比如csv这种类型的,需要跳过行首或者行尾一些和数据无关的或者自 ...

  7. 读取数据库数据,并将数据整合成3D饼图在jsp中显示

    首先我将生成饼图的方法独立写成一个PieChar.java类,详细代码如下:(数据库需要自己建,如有需要的话) import java.io.IOException; import java.sql. ...

  8. C# TCP socket发送大数据包时,接收端和发送端数据不一致 服务端接收Receive不完全

    简单的c# TCP通讯(TcpListener) C# 的TCP Socket (同步方式) C# 的TCP Socket (异步方式) C# 的tcp Socket设置自定义超时时间 C# TCP ...

  9. .NET读取Excel数据,提示错误:未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序

    解决.NET读取Excel数据时,提示错误:未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序的操作: 1. 检查本机是否安装Office Access,如果未安装去去h ...

随机推荐

  1. 转://Linux Multipath多路径配置与使用案例

    在Linux平台一部分存储产品使用操作系统自带的多路径软件,包括最常见的HP和IBM的部分存储产品,在Linux自带的多路径软件叫做multipath,这篇文章以HP EVA系列存储在Linux平台的 ...

  2. Nginx入门讲解——初步认识了解nginx.conf配置文件以及配置多个虚拟主机

    本文引自网络进攻学习之用https://blog.csdn.net/weixin_38111957/article/details/81080539 一. 引言上节文章讲述了如何用信号控制Nginx服 ...

  3. 【ES6】=>含义

    =>是es6语法中的arrow function (x) => x + 6 相当于 function(x){ return x + 6; }; var ids = this.sels.ma ...

  4. Linux systemctl命令笔记

    指令格式 systemctl [command] [unit] 常用指令 1.启动 $ systemctl start 2.停止 $ systemctl stop 3.重启 $ systemctl r ...

  5. 003_Git & Gitlab 使用指南

    2016-02-23   |   9,129字   |   分类于 工具  |   3条评论 去年小组在从 SVN 和 TFS 迁移到 Git 的过程中整理了这份文档,面向的用户是对 Git 和 SV ...

  6. sqlplus编译失效对象

    原文整理自:http://www.51testing.com/?uid-16403-action-viewspace-itemid-98161:http://www.eygle.com/archive ...

  7. ORA-16433 The database must be opened in read write mode故障解决

    转 一.首先删除原有控制文件并新建控制文件 1.找到控制文件位置 SQL> show parameter control_files; NAME TYPE VALUE ------------- ...

  8. Nginx(二)------nginx.conf 配置文件

    上一篇博客我们将 nginx 安装在 /usr/local/nginx 目录下,其默认的配置文件都放在这个目录的 conf 目录下,而主配置文件 nginx.conf 也在其中,后续对 nginx 的 ...

  9. Codechef SUMCUBE Sum of Cubes 组合、三元环计数

    传送门 好久没有做过图论题了-- 考虑\(k\)次方的组合意义,实际上,要求的所有方案中导出子图边数的\(k\)次方,等价于有顺序地选出其中\(k\)条边,计算它们在哪一些图中出现过,将所有方案计算出 ...

  10. CRectTracker类的使用

    CRectTracker(俗称“橡皮筋”类)是一个非常有意思的类.你在Windows中经常看到这样的情况:它可以用做显示边界,你也可以扽它的八个角用来放大缩小,或做框选使用.如何通过编程来实现这种功能 ...