You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
307 lines
11 KiB
307 lines
11 KiB
4 years ago
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Linq;
|
||
|
using System.Text;
|
||
|
using System.IO;
|
||
|
using System.Data;
|
||
|
using Common.Exceptions;
|
||
|
using Common.Data;
|
||
|
|
||
|
namespace NSC
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// 功能:网络报文解码器
|
||
|
/// 作者:王昊昇
|
||
|
/// 时间:2012.11.8
|
||
|
/// </summary>
|
||
|
internal static class PacketsDecoder
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// 解析网络数据流
|
||
|
/// </summary>
|
||
|
/// <param name="ms">来自网络的数据流</param>
|
||
|
/// <returns>返回通用服务数据结构体</returns>
|
||
|
internal static NetServiceStruct ParseNetStream(MemoryStream ms)
|
||
|
{
|
||
|
if (ms == null)
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
byte[] lengthBuffer = null;//长度缓存
|
||
|
int length = 0;//长度
|
||
|
byte[] priBuffer = null;//主体部分缓存
|
||
|
DataSet slvDataSet = null;//附件部分数据表
|
||
|
byte[] slvTmpBuffer = null;
|
||
|
Dictionary<int, byte[]> extData = new Dictionary<int, byte[]>();//二进制附件列表
|
||
|
|
||
|
ms.Position = 0;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
lengthBuffer = new byte[4];
|
||
|
ms.Read(lengthBuffer, 0, 4);
|
||
|
length = BitConverter.ToInt32(lengthBuffer, 0);//主体部分长度
|
||
|
|
||
|
priBuffer = new byte[length];
|
||
|
ms.Read(priBuffer, 0, length);//读取主体部分
|
||
|
|
||
|
while (ms.Position < ms.Length)
|
||
|
{
|
||
|
lengthBuffer = new byte[4];
|
||
|
ms.Read(lengthBuffer, 0, 4);
|
||
|
length = BitConverter.ToInt32(lengthBuffer, 0);//附件部分数据类型
|
||
|
|
||
|
switch (length)
|
||
|
{
|
||
|
case 0://DataTable
|
||
|
lengthBuffer = new byte[4];
|
||
|
ms.Read(lengthBuffer, 0, 4);
|
||
|
length = BitConverter.ToInt32(lengthBuffer, 0);//附件数据表部分长度
|
||
|
|
||
|
slvTmpBuffer = new byte[length];
|
||
|
ms.Read(slvTmpBuffer, 0, length);//读取附件数据表部分
|
||
|
|
||
|
slvDataSet = ByteArrayToDataSet(slvTmpBuffer);
|
||
|
break;
|
||
|
case 1://Binary
|
||
|
lengthBuffer = new byte[4];
|
||
|
ms.Read(lengthBuffer, 0, 4);
|
||
|
int index = BitConverter.ToInt32(lengthBuffer, 0);//二进制附件编号
|
||
|
|
||
|
lengthBuffer = new byte[4];
|
||
|
ms.Read(lengthBuffer, 0, 4);
|
||
|
length = BitConverter.ToInt32(lengthBuffer, 0);//二进制附件长度
|
||
|
|
||
|
byte[] extTmp = new byte[length];
|
||
|
ms.Read(extTmp, 0, length);//读取二进制附件
|
||
|
|
||
|
extData.Add(index, extTmp);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//解析主体部分
|
||
|
NetServiceStruct list = null;
|
||
|
using (MemoryStream priPart = new MemoryStream(priBuffer.Length))
|
||
|
{
|
||
|
priPart.Write(priBuffer, 0, priBuffer.Length);
|
||
|
|
||
|
list = ParseStreamData(priPart, slvDataSet, extData);
|
||
|
}
|
||
|
|
||
|
return list;
|
||
|
}
|
||
|
catch (Exception ex)
|
||
|
{
|
||
|
throw ex;
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
if (slvDataSet != null)
|
||
|
{
|
||
|
slvDataSet.Dispose();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 解析流数据
|
||
|
/// </summary>
|
||
|
/// <param name="priPart">主体数据流</param>
|
||
|
/// <returns>返回通用服务数据结构体</returns>
|
||
|
private static NetServiceStruct ParseStreamData(MemoryStream priPart, DataSet slvDataSet, Dictionary<int, byte[]> extData)
|
||
|
{
|
||
|
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
|
||
|
|
||
|
try
|
||
|
{
|
||
|
doc.LoadXml(Encoding.GetEncoding("gb2312").GetString(priPart.ToArray(), 0, (int)priPart.Length));
|
||
|
return ParseXML(doc, slvDataSet, extData);
|
||
|
}
|
||
|
catch (Exception ex)
|
||
|
{
|
||
|
throw ex;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 解码XML内容
|
||
|
/// </summary>
|
||
|
/// <param name="doc">XML对象</param>
|
||
|
/// <param name="slvDataSet">附件</param>
|
||
|
/// <returns>返回通用服务数据结构体</returns>
|
||
|
private static NetServiceStruct ParseXML(System.Xml.XmlDocument doc, DataSet slvDataSet, Dictionary<int, byte[]> extData)
|
||
|
{
|
||
|
NetServiceStruct nss = new NetServiceStruct();
|
||
|
System.Xml.XmlNode pNode = doc.SelectSingleNode("NetworkStreamData");
|
||
|
nss.FirmwareModel = Common.IO.XML.XMLUtil.GetAttribute(pNode, "FirmwareModel");
|
||
|
nss.FirmwareVersion = Common.IO.XML.XMLUtil.GetAttribute(pNode, "FirmwareVersion");
|
||
|
nss.UserName = Common.IO.XML.XMLUtil.GetAttribute(pNode, "UserName");
|
||
|
|
||
|
pNode = pNode.SelectSingleNode("ServiceDefine");
|
||
|
|
||
|
nss.ServiceName = Common.IO.XML.XMLUtil.GetAttribute(pNode, "ServiceName");
|
||
|
nss.ExceptionType = (ExceptionType)Enum.Parse(typeof(ExceptionType), Common.IO.XML.XMLUtil.GetAttribute(pNode, "Exception"), true);
|
||
|
nss.SyncType = (SyncType)Enum.Parse(typeof(SyncType), Common.IO.XML.XMLUtil.GetAttribute(pNode, "SyncType"), true);
|
||
|
nss.ServiceSN = Common.IO.XML.XMLUtil.GetAttribute(pNode, "ServiceSN");
|
||
|
nss.Params = new Dictionary<string, ParameterStruct>();
|
||
|
|
||
|
System.Xml.XmlNodeList args = pNode.SelectNodes("Param");
|
||
|
foreach (System.Xml.XmlNode a in args)
|
||
|
{
|
||
|
ParameterStruct ps = new ParameterStruct();
|
||
|
ps.DataFormat = Common.IO.XML.XMLUtil.GetAttribute(a, "Type");
|
||
|
ps.Link = Common.IO.XML.XMLUtil.GetAttribute(a, "Link");
|
||
|
if (ps.DataFormat == "IList" || ps.DataFormat == "Entity")
|
||
|
{
|
||
|
ps.Data = a;
|
||
|
}
|
||
|
else if (ps.DataFormat == "DataTable")
|
||
|
{
|
||
|
ps.Data = slvDataSet.Tables[ps.Link].Copy();
|
||
|
}
|
||
|
else if (ps.DataFormat == "Array")
|
||
|
{
|
||
|
ps.Data = ParseArray(a.SelectSingleNode("Items"));
|
||
|
}
|
||
|
else if (ps.DataFormat == "Binary")
|
||
|
{
|
||
|
ps.Data = extData[int.Parse(ps.Link)];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ps.SetData(Common.IO.XML.XMLUtil.GetAttribute(a, "Value"));
|
||
|
}
|
||
|
nss.Params.Add(Common.IO.XML.XMLUtil.GetAttribute(a, "Name"), ps);
|
||
|
}
|
||
|
|
||
|
System.Xml.XmlNodeList rets = pNode.SelectNodes("Return");
|
||
|
if (rets.Count > 0)
|
||
|
{
|
||
|
nss.Returns = new Dictionary<string, ParameterStruct>();
|
||
|
}
|
||
|
foreach (System.Xml.XmlNode r in rets)
|
||
|
{
|
||
|
ParameterStruct ps = new ParameterStruct();
|
||
|
ps.DataFormat = Common.IO.XML.XMLUtil.GetAttribute(r, "Type");
|
||
|
ps.Link = Common.IO.XML.XMLUtil.GetAttribute(r, "Link");
|
||
|
if (ps.DataFormat == "IList" || ps.DataFormat == "Entity")
|
||
|
{
|
||
|
ps.Data = r;
|
||
|
}
|
||
|
else if (ps.DataFormat == "DataTable")
|
||
|
{
|
||
|
ps.Data = slvDataSet.Tables[ps.Link].Copy();
|
||
|
}
|
||
|
else if (ps.DataFormat == "Array")
|
||
|
{
|
||
|
ps.Data = ParseArray(r.SelectSingleNode("Items"));
|
||
|
}
|
||
|
else if (ps.DataFormat == "Binary")
|
||
|
{
|
||
|
ps.Data = extData[int.Parse(ps.Link)];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ps.SetData(Common.IO.XML.XMLUtil.GetAttribute(r, "Value"));
|
||
|
}
|
||
|
nss.Returns.Add(Common.IO.XML.XMLUtil.GetAttribute(r, "Name"), ps);
|
||
|
}
|
||
|
|
||
|
return nss;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 解码字符串数组
|
||
|
/// </summary>
|
||
|
/// <param name="node">XML节点</param>
|
||
|
/// <returns>返回字符串数组</returns>
|
||
|
private static string[] ParseArray(System.Xml.XmlNode node)
|
||
|
{
|
||
|
string[] array = new string[node.ChildNodes.Count];
|
||
|
|
||
|
for (int i = 0; i < node.ChildNodes.Count; i++)
|
||
|
{
|
||
|
array[i] = Common.IO.XML.XMLUtil.GetAttribute(node.ChildNodes[i], "Value");
|
||
|
}
|
||
|
return array;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 解码数据流,可指定读取位置。只支持数据长度和数据链接在一起的数据
|
||
|
/// </summary>
|
||
|
/// <param name="ms">数据流</param>
|
||
|
/// <param name="position">读取位置</param>
|
||
|
/// <returns>返回流中的数据部分</returns>
|
||
|
private static byte[] ParseStream(MemoryStream ms, int position)
|
||
|
{
|
||
|
byte[] tmp = new byte[4];
|
||
|
ms.Read(tmp, position, tmp.Length);
|
||
|
int streamLength = BitConverter.ToInt32(tmp, 0);
|
||
|
if (streamLength > 0)
|
||
|
{
|
||
|
tmp = new byte[streamLength];
|
||
|
ms.Read(tmp, position + 4, tmp.Length);
|
||
|
return tmp;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 解码数据流。只支持数据长度和数据链接在一起的数据
|
||
|
/// </summary>
|
||
|
/// <param name="ms">数据流</param>
|
||
|
/// <returns>返回流中的数据部分</returns>
|
||
|
private static byte[] ParseStream(MemoryStream ms)
|
||
|
{
|
||
|
byte[] tmp = new byte[4];
|
||
|
ms.Read(tmp, (int)ms.Position, tmp.Length);
|
||
|
int streamLength = BitConverter.ToInt32(tmp, 0);
|
||
|
if (streamLength > 0)
|
||
|
{
|
||
|
tmp = new byte[streamLength];
|
||
|
ms.Read(tmp, (int)ms.Position, tmp.Length);
|
||
|
return tmp;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 将字节数组转换为数据表集合
|
||
|
/// </summary>
|
||
|
/// <param name="data">字节数组</param>
|
||
|
/// <returns>数据表集合</returns>
|
||
|
internal static DataSet ByteArrayToDataSet(byte[] data)
|
||
|
{
|
||
|
using (MemoryStream ms = new MemoryStream())
|
||
|
{
|
||
|
ms.Write(data, 0, data.Length);
|
||
|
|
||
|
ms.Position = 0;
|
||
|
|
||
|
System.Xml.XmlTextWriter xtw = new System.Xml.XmlTextWriter(ms, Encoding.GetEncoding("gb2312"));
|
||
|
xtw.WriteStartDocument();
|
||
|
|
||
|
//创建xml读取器
|
||
|
System.Xml.XmlTextReader xtr = new System.Xml.XmlTextReader(ms);
|
||
|
|
||
|
//创建数据集合
|
||
|
DataSet ds = new DataSet();
|
||
|
|
||
|
//将xml数据读入数据集合
|
||
|
ds.ReadXml(xtr, XmlReadMode.ReadSchema);
|
||
|
|
||
|
//返回数据集合
|
||
|
return ds;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|