基于.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 ...
随机推荐
- C++自定义修饰键,实现如<Capslock+J>等组合键的按键映射
前:所谓修饰键,就是Ctrl,Alt,Shift,Win这些按键. Update: 我使用AHK写了一个功能更丰富的脚本:https://github.com/h46incon/ModifierCus ...
- jquery简单入门(一)
相关: 本文参考<锋利的jQuery第二版> 写在前面: jQuery作为javascript框架,是做网页交互工作者,一个值得学习的优秀的前端框架... 百度指数分析:(http://i ...
- MySQL创建和操作数据库表demo
[1]建立员工档案表要求字段:员工员工编号,员工姓名,性别,工资,email,入职时间,部门. [2]合理选择数据类型及字段修饰符,要求有NOT NULL,auto_increment, primar ...
- C#设计模式(21)——责任链模式
一.引言 在现实生活中,有很多请求并不是一个人说了就算的,例如面试时的工资,低于1万的薪水可能技术经理就可以决定了,但是1万~1万5的薪水可能技术经理就没这个权利批准,可能就需要请求技术总监的批准,所 ...
- java 正则表达式的应用:读取文件,获取其中的电话号码
1.正则表达式 正则表达式,又称正规表示法.常规表示法(英语:Regular Expression,在代码中常简写为regex.regexp或RE),计算机科学的一个概念.正则表达式使用单个字符串来描 ...
- ELF Format 笔记(四)—— 节(Section)
ilocker:关注 Android 安全(新入行,0基础) QQ: 2597294287 ELF 文件可以包含很多 section,所有的 section 都在 section header tab ...
- JavaWeb学习----Cookie实现记住密码的功能
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- Zygote进程【3】——SystemServer的诞生
在ZygoteInit的main()方法中做了几件大事,其中一件便是启动Systemserver进程,代码如下: @/frameworks/base/core/Java/com/Android/int ...
- sql server 修改表结构语法大全
1.增加字段 ) 2.删除字段 alter table table_name drop column column_name 3.修改字段类型 alter table table_name alter ...
- li标签包含img的问题
我们在制作页面时,经常有可能碰到这样的设计: li 图一 图一的布局代码如下: <ul> <li><img src=”pic1.jpg” />& ...