基于.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.首先请求方进行发送一段报文。
- <?xml version="1.0" encoding="GBK"?>
- <Service>
- <Service_Header>
- <requester_id></requester_id>
- <branch_id ></branch_id>
- <service_time></service_time>
- <version_id></version_id>
- </Service_Header>
- <Service_Body>
- <request>
- <channel_type></channel_type>
- <cert_type></cert_type>
- <cert_no></cert_no>
- <query_type></query_type>
- <fr_id></fr_id>
- <pos_id></pos_id>
- <shop_id></shop_id>
- </request>
- </Service_Body>
- </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.响应的报文的序列化类
- [Serializable]
- public class ScoreDetailResponse : ApiResponse
- {
- /// <summary>
- /// 结果代码
- /// </summary>
- public string result_code { get;set; }
- /// <summary>
- /// 结果说明
- /// </summary>
- public string result_info { get;set; }
- /// <summary>
- /// 交易日期
- /// </summary>
- public string tran_date { get;set; }
- /// <summary>
- /// 交易时间
- /// </summary>
- public string tran_timestamp { get;set; }
- /// <summary>
- ///交易积分数
- /// </summary>
- public string transfer_score { get;set; }
- /// <summary>
- /// 剩余积分数
- /// </summary>
- public string surplus_score { get;set; }
- /// <summary>
- /// 备注
- /// </summary>
- public string remark { get;set; }
- }
- [Serializable]
- [XmlRoot("Service")]
- public class MyScoreDetailResponse
- {
- public List<ScoreDetailResponse> _ScoreDetailResponse = new List<ScoreDetailResponse>();
- [XmlArray("Service_Body")]
- [XmlArrayItem("response")]
- public List<ScoreDetailResponse> ScoreDetailResponse { get;set; }
- }
Serializable 类
2.序列化继承的接口和方法
- [XmlRoot("Service")]
- public class ApiResponse
- {
- [XmlElement("errCode")]
- public string ErrCode;
- [XmlElement("errMsg")]
- public string ErrMsg;
- public string Body { get; set; }
- }
- [XmlRoot("IFReturn")]
- public class IApiRequest { }
- [XmlRoot("IFReturn")]
- public class ApiRequest<T> : IApiRequest where T : ApiResponse
- {
- [XmlElement("channel_type")]
- public string channel_type { get; set; }
- [XmlElement("shop_id")]
- public string shop_id { get; set; }
- [XmlElement("post_id")]
- public string post_id { get; set; }
- }
- public interface IParser
- {
- /// <summary>
- /// 把响应字符串解释成相应的领域对象。
- /// </summary>
- /// <typeparam name="T">领域对象</typeparam>
- /// <param name="body">响应字符串</param>
- /// <returns>领域对象</returns>
- T XMLParse<T>(string body) where T : ApiResponse;
- /// <summary>
- /// 将对象转换为XML
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="body"></param>
- /// <returns></returns>
- string Parse<T>(T body) where T : IApiRequest;
- }
- public class XmlParse:IParser
- {
- #region Field
- private static readonly Regex regex = new Regex("<(\\w+?)[ >]", RegexOptions.Compiled);
- private static readonly ReaderWriterLock rwLock = new ReaderWriterLock();
- private static readonly Dictionary<string, XmlSerializer> parsers = new Dictionary<string, XmlSerializer>();
- #endregion
- #region Members
- /// <summary>
- /// 将XML转换为对象
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="body"></param>
- /// <returns></returns>
- public T ParseDeserialize<T>(string body) where T : ApiResponse
- {
- Type type = typeof(T);
- string rootTagName = GetRootElement(body);
- string key = type.FullName;
- if (Constants.ERROR_RESPONSE.Equals(rootTagName))
- {
- key += ("_" + Constants.ERROR_RESPONSE);
- }
- XmlSerializer serializer = null;
- bool incl = false;
- rwLock.AcquireReaderLock();
- try
- {
- if (rwLock.IsReaderLockHeld)
- {
- incl = parsers.TryGetValue(key, out serializer);
- }
- }
- finally
- {
- if (rwLock.IsReaderLockHeld)
- {
- rwLock.ReleaseReaderLock();
- }
- }
- if (!incl || serializer == null)
- {
- XmlAttributes rootAttrs = new XmlAttributes();
- rootAttrs.XmlRoot = new XmlRootAttribute(rootTagName);
- XmlAttributeOverrides attrOvrs = new XmlAttributeOverrides();
- attrOvrs.Add(type, rootAttrs);
- serializer = new XmlSerializer(type, attrOvrs);
- rwLock.AcquireWriterLock();
- try
- {
- if (rwLock.IsWriterLockHeld)
- {
- parsers[key] = serializer;
- }
- }
- finally
- {
- if (rwLock.IsWriterLockHeld)
- {
- rwLock.ReleaseWriterLock();
- }
- }
- }
- object obj = null;
- using (System.IO.Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(body)))
- {
- obj = serializer.Deserialize(stream);
- }
- T rsp = (T)obj;
- if (rsp != null)
- {
- rsp.Body = body;
- }
- return rsp;
- }
- /// <summary>
- /// 将对象转换为XML
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="obj"></param>
- /// <returns></returns>
- public string Parse<T>(T obj) where T : IApiRequest
- {
- XmlSerializer serializer = null;
- serializer = new XmlSerializer(obj.GetType());
- XmlSerializerNamespaces xmlns = new XmlSerializerNamespaces();
- xmlns.Add("", "");
- string xml = null;
- using (MemoryStream stream = new MemoryStream())
- {
- serializer.Serialize(stream, obj, xmlns);
- xml = Encoding.UTF8.GetString(stream.ToArray());
- }
- return xml;
- }
- #endregion
- /// <summary>
- /// 获取XML响应的根节点名称
- /// </summary>
- private string GetRootElement(string body)
- {
- Match match = regex.Match(body);
- if (match.Success)
- {
- return match.Groups[].ToString();
- }
- else
- {
- throw new Exception("Invalid XML response format!");
- }
- }
- public T XMLParse<T>(string body) where T : ApiResponse
- {
- throw new NotImplementedException();
- }
- /// <summary>
- /// 将XML文件进行反序列话进行对象
- /// </summary>
- /// <typeparam name="T">结果对象类型</typeparam>
- /// <param name="s">包含对象的XML字符串</param>
- /// <param name="encoding">编码方式</param>
- /// <returns>反序列化得到的对象</returns>
- public T XmlDeserialize<T>(string s)
- {
- if (string.IsNullOrEmpty(s))
- {
- throw new ArgumentNullException("s");
- }
- XmlSerializer mySerializer = new XmlSerializer(typeof(T));
- using (MemoryStream ms = new MemoryStream(Encoding.GetEncoding("utf-8").GetBytes(s)))
- {
- using (StreamReader sr = new StreamReader(ms, Encoding.GetEncoding("utf-8")))
- {
- return (T)mySerializer.Deserialize(sr);
- }
- }
- }
- }
- public sealed class Constants
- {
- public const string DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
- public const string SIGN_METHOD_MD5 = "md5";
- public const string ACCEPT_ENCODING = "Accept-Encoding";
- public const string CONTENT_ENCODING = "Content-Encoding";
- public const string CONTENT_ENCODING_GZIP = "gzip";
- public const string ERROR_RESPONSE = "error_response";
- public const string ERROR_CODE = "code";
- public const string ERROR_MSG = "msg";
- }
反序列化进行解析代码
3.通过控制台应用进行调用
- #region 获取TCPClient 返回的结果
- /// <summary>
- /// 获取TCPClient 返回的结果
- /// </summary>
- /// <param name="s"></param>
- /// <param name="trans_id">服务器交易码</param>
- /// <returns></returns>
- private string GetTcpClientResult(MemoryStream s, string trans_id)
- {
- byte[] bufTemp = s.ToArray();
- string xmlContent = bufTemp.Length.ToString().PadLeft(, '') + "xxxx" + trans_id + Encoding.GetEncoding("GBK").GetString(bufTemp);
- byte[] buf = Encoding.GetEncoding("GBK").GetBytes(xmlContent);
- string svrAddr = Properties.Settings.Default.TCP_IP;//对方服务器的IP
- int svrPort = Properties.Settings.Default.TCP_PORT;//请求的服务器的端口
- using (TcpClient tcpClient = new TcpClient(svrAddr, svrPort))
- {
- var tcpStream = tcpClient.GetStream();
- tcpStream.Write(buf, , buf.Length);
- byte[] recv = new byte[];
- int recvLen = tcpStream.Read(recv, , recv.Length);
- string result = Encoding.GetEncoding("GBK").GetString(recv, , recvLen);
- tcpClient.Close();
- return result;
- }
- }
- #endregion
TcpClient 应用Scoket进行发送请求
四:整个Scoket 请求处理响应的流程图
以上内容全部原创,如需转载,请标明,谢谢!
基于.NET Socket API 通信的综合应用的更多相关文章
- 【Java TCP/IP Socket】基于NIO的TCP通信(含代码)
NIO主要原理及使用 NIO采取通道(Channel)和缓冲区(Buffer)来传输和保存数据,它是非阻塞式的I/O,即在等待连接.读写数据(这些都是在一线程以客户端的程序中会阻塞线程的操作)的时候, ...
- Python网络编程03 /缓存区、基于TCP的socket循环通信、执行远程命令、socketserver通信
Python网络编程03 /缓存区.基于TCP的socket循环通信.执行远程命令.socketserver通信 目录 Python网络编程03 /缓存区.基于TCP的socket循环通信.执行远程命 ...
- 基于.NET Socket Tcp的发布-订阅框架
基于.NET Socket Tcp的发布-订阅框架 一.分布式消息总线 在很多MIS项目之中都有这样的需求,需要一个及时.高效的的通知机制,即比如当使用者A完成了任务X,就需要立即告知使用者B任务X已 ...
- Socket进程通信机制及应用
Socket通常称为“套接字”,用于描述IP地址和端口,是一个通信链的句柄.应用程序通过套接字向网络发出请求或者应答网络请求.Socket即不是一个程序,也不是一个协议,其只是操作系统提供的通信层的一 ...
- socket编程 ------ BSD socket API
伯克利套接字(Berkeley sockets),也称为BSD Socket.伯克利套接字的应用编程接口(API)是采用C语言的进程间通信的库,经常用在计算机网络间的通信. BSD Socket的应用 ...
- 基于JAVA Socket的底层原理分析及工具实现
前言 在工作开始之前,我们先来了解一下Socket 所谓Socket,又被称作套接字,它是一个抽象层,简单来说就是存在于不同平台(os)的公共接口.学过网络的同学可以把它理解为基于传输TCP/IP协议 ...
- 分布式消息总线,基于.NET Socket Tcp的发布-订阅框架之离线支持,附代码下载
一.分布式消息总线以及基于Socket的实现 在前面的分享一个分布式消息总线,基于.NET Socket Tcp的发布-订阅框架,附代码下载一文之中给大家分享和介绍了一个极其简单也非常容易上的基于.N ...
- TCP/IP协议学习(五) 基于C# Socket的C/S模型
TCP/IP协议作为现代网络通讯的基石,内容包罗万象,直接去理解理论是比较困难的:然而通过实践先理解网络通讯的理解,在反过来理解学习TCP/IP协议栈就相对简单很多.C#通过提供的Socket API ...
- JAVA基础知识之网络编程——-基于UDP协议的通信例子
UDP是一种不可靠的协议,它在通信两端各建立一个socket,这两个socket不会建立持久的通信连接,只会单方面向对方发送数据,不检查发送结果. java中基于UDP协议的通信使用DatagramS ...
随机推荐
- SQL Server 2000: 维护计划无法执行
开启“sql server agent”服务,控制面板-->管理工具-->服务
- Open Auth辅助库(使用ImitateLogin实现登录)
网络上越来越多的公司进行着自己的平台化策略,其中绝大多数都已Web API的方式对外提供服务,为了方便的使用这些服务,你不得不引用许多相关的类库,但是API的本质其实仅仅是一些约定的网络请求,我们大多 ...
- Spring MVC - 配置Spring MVC
写在前面的话: 现在开始一段新的学习历程:Spring MVC.还是按照原来的三步走学习模式(what.why.how)进行讲解. 1.Spring MVC是什么(what) Spring MVC属于 ...
- Linux IPC Pipe
mkfifo() //创建有名管道(FIFO special file),创建完了就像普通文件一样open(),再读写,成功返回0,失败返回-1设errno.VS$man 3 mkfifo #incl ...
- ELF Format 笔记(五)—— 特殊 Section
ilocker:关注 Android 安全(新入行,0基础) QQ: 2597294287 链接器把一些独立的 object files 和库文件链接起来,形成可执行文件.在这个过程中,链接器需要解决 ...
- Win8 忘记密码 解决办法【在E450c实测有效】
工具/原料 已经刻录通用PE工具箱的U盘 方法/步骤 1 首先来看一下,问题产生的状况.出现登陆界面,由于密码忘记,怎么输入密码,老是提示密码错误 2 接下来,按住Shift,电脑关机重启,也就是 ...
- FineReport构建银行金融租赁考核系统
一.应用背景 我们今天以民生银行为案例来交大家如何利用报表工具搭建金融租赁考核系统.民生银行在IT建设上已经建设邮件系统.外部网站系统.视频会议系统.OA系统.财务系统.自助报销系统.核心系统.资金管 ...
- css3常用动画+动画库
一.animates.css animate.css是来自dropbox的工程师Daniel Eden开发的一款CSS3的动画效果小类库.包含了60多款不同类型的CSS3动画,包括:晃动,闪动,各种淡 ...
- [Top-Down Approach] Chatper 4 Notes
4.2 Virtual Circuit and Datagram Networks VC Set up connection Exchange data Free the connection The ...
- Mobizen免帐号版
Mobizen电脑控制手机软件,是远程软件专家RSUPPORT公司研发的一款全新产品,可以通过电脑(web页面和客户端两种形式)远程控制安卓系统的智能手机和平板电脑,三种连接方式3G/4G.Wifi. ...