zoukankan      html  css  js  c++  java
  • 基于.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 请求处理响应的流程图

     

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

     

     

    再牛逼的梦想,也抵不住我傻逼似的坚持!别在该奋斗的年纪,贪图安逸。 今天多学一些知识,明天开发的速度就更快一下。后天你就会变得更好。
  • 相关阅读:
    JDK源码之Thread 类分析
    java中符号类型和无符号类型的问题分析
    国内高速Maven仓库
    Idea Live Templates代码模板
    正则表达式
    java内存泄漏
    MySQL查看 InnoDB表中每个索引的高度
    ThreadLocalMap里Entry为何声明为WeakReference?
    Java JDBC中,MySQL字段类型到JAVA类型的转换
    MyBatis查询两个字段,返回Map,一个字段作为key,一个字段作为value的实现
  • 原文地址:https://www.cnblogs.com/LowKeyCXY/p/6128863.html
Copyright © 2011-2022 走看看