基于.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 ...
随机推荐
- [转载]DBA的特质第一部分:技术
本文转自http://www.searchdatabase.com.cn/showcontent_84379.htm 支持原创.尊重原创,分享知识! 在本系列文章中,笔者将谈一谈数据库管理员(DBA) ...
- MySQL锁机制总结(二)
前言: Mysql是一个支持插件式存储引擎的数据库系统,本文讨论的锁机制也主要包含两部分SERVER层的锁和存储引擎的锁,存储引擎是指innodb,其它存储引暂不讨论. 1. 数据库中锁相关的基本概念 ...
- PowerBI通过gateway连接多维数据库
简介 Microsoft Power BI 是由微软推出的商业智能的专业分析工具,给用户提供简单且丰富的数据可视化及分析功能.个人非常喜欢,有免费版和Pro的付费版,今天主要是介绍下通过gatew ...
- Netty 异步的、事件驱动的网络应用程序框架和工具
Netty是由JBOSS提供的一个Java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. 项目地址:https://githu ...
- 新手开发android容易出现的错误(不断更新中...)
才开始开发android app,因为以前一直是java开发,学习也比较容易. 记录下自己开发过程中出现的一些小问题: 静态变量 在开发中,因为习惯性的问题,经常将一些常用数据(如用户信息等)进行st ...
- 大数据挖掘: FPGrowth初识--进行商品关联规则挖掘
@(hadoop)[Spark, MLlib, 数据挖掘, 关联规则, 算法] [TOC] 〇.简介 经典的关联规则挖掘算法包括Apriori算法和FP-growth算法.Apriori算法多次扫描交 ...
- Linux磁盘管理之日志文件系统和非日志文件系统08
略. 查看linux支持的文件系统命令: ls /lib/module/`uname -r`/x86/fs blkid查看文件系统的类型 mkfs.ext2 == mkfs –t ext2
- android 读取根目录下的文件或文件夹
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setC ...
- LNMP环境搭建
LNMP环境搭建 Linux + Nginx + MySQL + PHP PHP是一种脚本语言,当前中国乃至世界上使用PHP语言开发的网站非常普遍 Nginx是一个web服务软件,和apache是一类 ...
- Log4Net根据不同的Logger名称,生成日志文件到不同的地方。
1.定义日志记录类 1: public class Log4NetLogger : ISystemLogger 2: { 3: static log4net.ILog securityLogger = ...