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 { /// /// 功能:网络报文解码器 /// 作者:王昊昇 /// 时间:2012.11.8 /// internal static class PacketsDecoder { /// /// 解析网络数据流 /// /// 来自网络的数据流 /// 返回通用服务数据结构体 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 extData = new Dictionary();//二进制附件列表 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(); } } } /// /// 解析流数据 /// /// 主体数据流 /// 返回通用服务数据结构体 private static NetServiceStruct ParseStreamData(MemoryStream priPart, DataSet slvDataSet, Dictionary 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; } } /// /// 解码XML内容 /// /// XML对象 /// 附件 /// 返回通用服务数据结构体 private static NetServiceStruct ParseXML(System.Xml.XmlDocument doc, DataSet slvDataSet, Dictionary 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(); 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(); } 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; } /// /// 解码字符串数组 /// /// XML节点 /// 返回字符串数组 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; } /// /// 解码数据流,可指定读取位置。只支持数据长度和数据链接在一起的数据 /// /// 数据流 /// 读取位置 /// 返回流中的数据部分 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; } } /// /// 解码数据流。只支持数据长度和数据链接在一起的数据 /// /// 数据流 /// 返回流中的数据部分 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; } } /// /// 将字节数组转换为数据表集合 /// /// 字节数组 /// 数据表集合 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; } } } }