基于.NET Socket API 通信的综合应用


闲谈一下,最近和客户进行对接Scoket 本地的程序作为请求方以及接受方,对接Scoket 的难度实在比较大,因为涉及到响应方返回的报文的不一致性,对于返回的报文的格式我需要做反序列化的难度增大了不少,下面我就谈谈如果基于进行对接Scoket API 的接口的。方便大家,节省时间,少走弯路。大大的提高自己的开发的效率,当然我介绍的只是基于.NET Scoket API 的应用。 

一.Scoket 的简介以及和WebServices WCF的区别

1.网络上经常通过程序进行双方的通信,但是在这个过程中,需要进行数据的交换。那么在这个过程中,需要进行建立网络的通讯。

2.通过请求方发出一段报文,给响应方,进行接收,并返回请求报文的结果。

3.所以基于Socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口(经过3次握手),这个就是所谓的Socket编程接口。

4.基于Scoket API 的编程的接口 与WebServices 以及 WebAPI不同的后者都是基于HTTP请求的,但是WCF整合了原有的windows通讯的 .NET Remoting,WebService,Socket的机制,并融合有HTTP 和FTP 的相关技术。进行面向数据通信的程序框架。

5.Socket是面向客户以及服务器模型而设计。 

二:Scoket 的综合的应用

1.Scoket流程图

2.首先请求方进行发送一段报文。

 1 <?xml version="1.0" encoding="GBK"?>
 2 <Service>
 3     <Service_Header>
 4         <requester_id></requester_id>
 5         <branch_id ></branch_id>
 6         <service_time></service_time>
 7         <version_id></version_id>
 8     </Service_Header>
 9     <Service_Body>
10         <request>
11             <channel_type></channel_type>
12       <cert_type></cert_type>
13       <cert_no></cert_no>
14       <query_type></query_type>
15       <fr_id></fr_id>
16             <pos_id></pos_id>
17             <shop_id></shop_id>
18         </request>
19     </Service_Body>
20 </Service>
请求的报文

3.响应方返回的报文的格式

<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<Service>
  <Service_Header>
    <reply_qmgr>FT1_IN01</reply_qmgr>
    <service_response>
      <code>0000</code>
      <desc>成功</desc>
      <status>COMPLETE</status>
    </service_response>
    <msglog></msglog>
    <timeout>150</timeout>
    <name>积分查询</name>
    <start_time>1466155364977</start_time>
    <start_timestamp>2016-06-17 17:22:44.976</start_timestamp>
    <service_id>05170000000001</service_id>
    <requester_id>0324</requester_id>
    <branch_id>1</branch_id>
    <service_time>20160617</service_time>
    <version_id>001</version_id>
    <trace_msg>Reply to responseQ - IBM.SERVICE.RESPONSE.OUT.AFA: FT1_IN01</trace_msg>
    <end_timestamp>2016-06-17 09:22:45.327</end_timestamp>
  </Service_Header>
  <Service_Body>
    <request>
      <channel_type>01</channel_type>
      <card_num>6224520110000004232</card_num>
      <mobie_phone></mobie_phone>
      <pos_id></pos_id>
      <shop_id></shop_id>
    </request>
    <response>
      <result_code>0000</result_code>
      <result_info>成功</result_info>
      <ims_serial_no/>
      <total_num>101.0</total_num>
      <score_num>101.0</score_num>
      <freeze_num>0.0</freeze_num>
    </response>
  </Service_Body>
</Service>
响应的报文

三.通过序列化以及反序列化进行解析报文

1.响应的报文的序列化类

 1  [Serializable]  2     public class ScoreDetailResponse : ApiResponse  3  {  4         /// <summary>
 5         /// 结果代码  6         /// </summary>
 7         public string result_code { get;set; }  8 
 9         /// <summary>
10         /// 结果说明 11         /// </summary>
12         public string result_info { get;set; } 13 
14         /// <summary>
15         /// 交易日期 16         /// </summary>
17         public string tran_date { get;set; } 18 
19         /// <summary>
20         /// 交易时间 21         /// </summary>
22         public string tran_timestamp { get;set; } 23 
24          /// <summary>
25          ///交易积分数 26          /// </summary>
27          public string transfer_score { get;set; } 28          
29          /// <summary>
30          /// 剩余积分数 31          /// </summary>
32          public string surplus_score { get;set; } 33          
34          /// <summary>
35          /// 备注 36          /// </summary>
37          public string remark { get;set; } 38 
39 
40  } 41  [Serializable] 42     [XmlRoot("Service")] 43     public class MyScoreDetailResponse 44  { 45         public List<ScoreDetailResponse> _ScoreDetailResponse = new List<ScoreDetailResponse>(); 46         [XmlArray("Service_Body")] 47         [XmlArrayItem("response")] 48         public List<ScoreDetailResponse> ScoreDetailResponse { get;set; } 49     }
Serializable 类

2.序列化继承的接口和方法

 1 [XmlRoot("Service")]  2     public  class ApiResponse  3  {  4         [XmlElement("errCode")]  5         public string ErrCode;  6 
 7         [XmlElement("errMsg")]  8         public string ErrMsg;  9 
 10         public string Body { get; set; }  11  }  12 
 13 
 14    [XmlRoot("IFReturn")]  15         public class IApiRequest { }  16         [XmlRoot("IFReturn")]  17         public class ApiRequest<T> : IApiRequest where T : ApiResponse  18  {  19             [XmlElement("channel_type")]  20             public string channel_type { get; set; }  21 
 22             [XmlElement("shop_id")]  23             public string  shop_id { get; set; }  24 
 25             [XmlElement("post_id")]  26             public string post_id { get; set; }  27  }  28 
 29 
 30  public interface IParser  31  {  32         /// <summary>
 33         /// 把响应字符串解释成相应的领域对象。  34         /// </summary>
 35         /// <typeparam name="T">领域对象</typeparam>
 36         /// <param name="body">响应字符串</param>
 37         /// <returns>领域对象</returns>
 38         T XMLParse<T>(string body) where T : ApiResponse;  39 
 40         /// <summary>
 41         /// 将对象转换为XML  42         /// </summary>
 43         /// <typeparam name="T"></typeparam>
 44         /// <param name="body"></param>
 45         /// <returns></returns>
 46         string Parse<T>(T body) where T : IApiRequest;  47  }  48 
 49 
 50 
 51 public class XmlParse:IParser  52  {  53         #region Field
 54         private static readonly Regex regex = new Regex("<(\\w+?)[ >]", RegexOptions.Compiled);  55         private static readonly ReaderWriterLock rwLock = new ReaderWriterLock();  56         private static readonly Dictionary<string, XmlSerializer> parsers = new Dictionary<string, XmlSerializer>();  57         #endregion
 58 
 59         #region Members
 60         /// <summary>
 61         /// 将XML转换为对象  62         /// </summary>
 63         /// <typeparam name="T"></typeparam>
 64         /// <param name="body"></param>
 65         /// <returns></returns>
 66         public T ParseDeserialize<T>(string body) where T : ApiResponse  67  {  68             Type type = typeof(T);  69             string rootTagName = GetRootElement(body);  70 
 71             string key = type.FullName;  72             if (Constants.ERROR_RESPONSE.Equals(rootTagName))  73  {  74                 key += ("_" + Constants.ERROR_RESPONSE);  75  }  76 
 77             XmlSerializer serializer = null;  78             bool incl = false;  79 
 80             rwLock.AcquireReaderLock(50);  81             try
 82  {  83                 if (rwLock.IsReaderLockHeld)  84  {  85                     incl = parsers.TryGetValue(key, out serializer);  86  }  87  }  88             finally
 89  {  90                 if (rwLock.IsReaderLockHeld)  91  {  92  rwLock.ReleaseReaderLock();  93  }  94  }  95 
 96             if (!incl || serializer == null)  97  {  98                 XmlAttributes rootAttrs = new XmlAttributes();  99                 rootAttrs.XmlRoot = new XmlRootAttribute(rootTagName); 100 
101                 XmlAttributeOverrides attrOvrs = new XmlAttributeOverrides(); 102  attrOvrs.Add(type, rootAttrs); 103 
104                 serializer = new XmlSerializer(type, attrOvrs); 105 
106                 rwLock.AcquireWriterLock(50); 107                 try
108  { 109                     if (rwLock.IsWriterLockHeld) 110  { 111                         parsers[key] = serializer; 112  } 113  } 114                 finally
115  { 116                     if (rwLock.IsWriterLockHeld) 117  { 118  rwLock.ReleaseWriterLock(); 119  } 120  } 121  } 122             object obj = null; 123             using (System.IO.Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(body))) 124  { 125                 obj = serializer.Deserialize(stream); 126  } 127 
128             T rsp = (T)obj; 129             if (rsp != null) 130  { 131                 rsp.Body = body; 132  } 133             return rsp; 134  } 135 
136         /// <summary>
137         /// 将对象转换为XML 138         /// </summary>
139         /// <typeparam name="T"></typeparam>
140         /// <param name="obj"></param>
141         /// <returns></returns>
142         public string Parse<T>(T obj) where T : IApiRequest 143  { 144             XmlSerializer serializer = null; 145 
146             serializer = new XmlSerializer(obj.GetType()); 147             XmlSerializerNamespaces xmlns = new XmlSerializerNamespaces(); 148             xmlns.Add("", ""); 149 
150             string xml = null; 151             using (MemoryStream stream = new MemoryStream()) 152  { 153  serializer.Serialize(stream, obj, xmlns); 154                 xml = Encoding.UTF8.GetString(stream.ToArray()); 155  } 156 
157             return xml; 158  } 159         #endregion
160 
161         /// <summary>
162         /// 获取XML响应的根节点名称 163         /// </summary>
164         private string GetRootElement(string body) 165  { 166             Match match = regex.Match(body); 167             if (match.Success) 168  { 169                 return match.Groups[1].ToString(); 170  } 171             else
172  { 173                 throw new Exception("Invalid XML response format!"); 174  } 175  } 176 
177         public T XMLParse<T>(string body) where T : ApiResponse 178  { 179             throw new NotImplementedException(); 180  } 181 
182 
183         /// <summary>
184         /// 将XML文件进行反序列话进行对象 185         /// </summary>
186         /// <typeparam name="T">结果对象类型</typeparam>
187         /// <param name="s">包含对象的XML字符串</param>
188         /// <param name="encoding">编码方式</param>
189         /// <returns>反序列化得到的对象</returns>
190         public  T XmlDeserialize<T>(string s) 191  { 192             if (string.IsNullOrEmpty(s)) 193  { 194                 throw new ArgumentNullException("s"); 195  } 196             XmlSerializer mySerializer = new XmlSerializer(typeof(T)); 197             using (MemoryStream ms = new MemoryStream(Encoding.GetEncoding("utf-8").GetBytes(s))) 198  { 199                 using (StreamReader sr = new StreamReader(ms, Encoding.GetEncoding("utf-8"))) 200  { 201                     return (T)mySerializer.Deserialize(sr); 202  } 203  } 204  } 205 
206  } 207 
208 
209    public sealed class Constants 210  { 211        public const string DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; 212 
213        public const string SIGN_METHOD_MD5 = "md5"; 214 
215        public const string ACCEPT_ENCODING = "Accept-Encoding"; 216        public const string CONTENT_ENCODING = "Content-Encoding"; 217        public const string CONTENT_ENCODING_GZIP = "gzip"; 218 
219        public const string ERROR_RESPONSE = "error_response"; 220        public const string ERROR_CODE = "code"; 221        public const string ERROR_MSG = "msg"; 222    }
反序列化进行解析代码

3.通过控制台应用进行调用

 1  #region 获取TCPClient 返回的结果
 2         /// <summary>
 3         /// 获取TCPClient 返回的结果  4         /// </summary>
 5         /// <param name="s"></param>
 6         /// <param name="trans_id">服务器交易码</param>
 7         /// <returns></returns>
 8         private string GetTcpClientResult(MemoryStream s, string trans_id)  9  { 10             byte[] bufTemp = s.ToArray(); 11             string xmlContent = bufTemp.Length.ToString().PadLeft(10, '0') + "xxxx" + trans_id + Encoding.GetEncoding("GBK").GetString(bufTemp); 12             byte[] buf = Encoding.GetEncoding("GBK").GetBytes(xmlContent); 13             string svrAddr = Properties.Settings.Default.TCP_IP;//对方服务器的IP
14             int svrPort = Properties.Settings.Default.TCP_PORT;//请求的服务器的端口
15 
16             using (TcpClient tcpClient = new TcpClient(svrAddr, svrPort)) 17  { 18                 var tcpStream = tcpClient.GetStream(); 19                 tcpStream.Write(buf, 0, buf.Length); 20                 byte[] recv = new byte[4096]; 21                 int recvLen = tcpStream.Read(recv, 0, recv.Length); 22                 string result = Encoding.GetEncoding("GBK").GetString(recv, 0, recvLen); 23  tcpClient.Close(); 24                 return result; 25  } 26  } 27         #endregion
TcpClient 应用Scoket进行发送请求

 

四:整个Scoket 请求处理响应的流程图

 

以上内容全部原创,如需转载,请标明,谢谢!

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM