.net 平台下, Socket通讯协议中间件设计思路(附源码)
.net 平台下,实现通讯处理有很多方法(见下表),各有利弊:
| 序号 | 实现方式 | 特点 |
| 1 | WCF | 优点:封装好,方便。缺点:难学,不跨平台 |
| 2 |
RocketMQ,SuperSocket等中间件 |
优点:轻便 缺点:用户群体少 |
| 3 | 直接使用winsocket | 优点:全部在自己掌控之下,协议灵活。缺点:实现时间长,易于出错。 |
本人开发socket通讯多年了,一直干着“重复发明轮子”工作,这种工作方式效率低下,容易出错!
重复的事情做多了,也会出现“灵光“!何不自己设计一套中间件,在此基础上,再设计应用层协议。就可以避免“重复发明轮子”。
先看下图,协议栈:

本文讲述的就是绿色部分如何设计。
这层协议设计原则有:
- 要简单 有两层意思:一是协议简单;再者使用起来简单。并且可以满足大部分应用场景。
- 可以跨平台 .net core本身可以跨平台。 如果对方使用c、c++开发,用其他语言实现该协议也不难。
- 隐藏底层细节 应用层,处理对象都是.net类,而不是字节流。
- 可以大数据传输 无论传输多大的数据,不必考虑分包合包处理。
设计思路
总的原则是,传输的是.net平台下的类,而不是字节流。直接处理.net类要比字节流要方便,安全很多。
.net平台下类型很多,我提取了最常用的几种,达到即简单,又满足大部分应用场景的要求。
可以传输的类型有:int、string、short、long,byte;
以及对应链表类型: List<int>、List<string>、List<short>、List<long>、byte[];

协议总的包体:
public class NetPacket
{
public int PacketType { get; set; } // 包类型
public int Param1 { get; set; } // 参数1 ,可以根据实际情况使用
public int Param2 { get; set; } // 参数2 ,可以根据实际情况使用
public List<NetValuePair> Items { get; set; } //传输的key value 列表
}
NetValuePair 定义如下:
public class NetValuePair
{
public string Key { get; set; }
public NetValueBase Value { get; set; } public NetValuePair()
{ }
}
NetValueBase 包含子类型,分别对应string、int等。以string类型举例:
public class NetValueBase
{
public EN_DataType ValueType { get;protected set; } public virtual object GetValue()
{
return null;
}
}
public class NetValueString: NetValueBase
{
public string Value { get; set; } = string.Empty;
public override object GetValue()
{
return Value;
} public NetValueString()
{
ValueType = EN_DataType.en_string;
} public NetValueString(string value)
{
ValueType = EN_DataType.en_string;
Value = value;
}
}
NetValueString值最终要以字节流方式传送出去,采用如下方式序列化:
string值采用utf8传输,先将字符串转换成字节流;分别写入字节流的长度,实际的字节流;
在序列化中,没用多余字段。比.net 自带的序列化类处理要高效的多,大家可以对比下。
internal static void WriteStringValue(Stream stream, string value)
{
byte[] bytes = Encoding.UTF8.GetBytes(value); WriteInt32(stream, bytes.Length);
stream.Write(bytes, 0, bytes.Length);
}
其它类型的序列化,与此类似,不在累述。反序列化如何操作,也不难想像。
传输
序列化后的数据要发送出去,需要下一层来处理。
这层的主要功能就是分包和合包。(数据很小的时候就不需要分包了)
public class RawNetPacket
{
public static int HeadLen = 14;
public UInt16 PacketLen;
public UInt32 PacketId; //一个完整的包 唯一id
public UInt32 TotalNO; //共有多少个包
public UInt32 PacketNO; //包序列号
public byte[] Body; //承载NetPacket序列化的数据,有可能分包发送
}
具体如何分包和合包,可以参考附件源码。
使用举例
1 传送文件
private NetPacket GetPacketByFile(string fileName)
{
using (FileStream stream = new FileInfo(fileName).OpenRead())
{
NetPacket result = new NetPacket();
result.PacketType = 2;
result.Param1 = 2;
result.Param2 = 3;
result.Items = new List<NetValuePair>(); //string
NetValuePair pair = new NetValuePair();
pair.Key = "文件名称";
pair.Value = new NetValueString(fileName);
result.Items.Add(pair); //byte
pair = new NetValuePair();
pair.Key = "文件二进制数据";
NetValueListByte fileBuffer = new NetValueListByte();
fileBuffer.Value = new byte[stream.Length];
stream.Read(fileBuffer.Value, 0, Convert.ToInt32(stream.Length)); pair.Value = fileBuffer;
result.Items.Add(pair);
return result;
}
}
2 传输对象
可以将对象序列化为json字符串,再传送。
.net 平台下, Socket通讯协议中间件设计思路(附源码)的更多相关文章
- YYCache设计思路及源码学习
设计思路 利用YYCache来进行操作,实质操作分为了内存缓存操作(YYMemoryCache)和硬盘缓存操作(YYDiskCache).内存缓存设计一般是在内存中开辟一个空间用以保存请求的数据(一般 ...
- 可在广域网部署运行的即时通讯系统 -- GGTalk总览(附源码下载)
(最新版本:V6.2,2019.01.03 .Xamarin移动端版本已经推出,包括 Android 和 iOS) GGTalk开源即时通讯系统(简称GG)是QQ的高仿版,同时支持局域网和广域网, ...
- 【转】可在广域网部署运行的即时通讯系统 -- GGTalk总览(附源码下载)
原文地址:http://www.cnblogs.com/justnow/p/3382160.html (最新版本:V6.0,2017.12.11 .即将推出Xamarin移动端版本,包括 Androi ...
- asp.net abp模块化开发之通用树2:设计思路及源码解析
一.前言 上一篇大概说了下abp通用树形模块如何使用,本篇主要分析下设计思路. 日常开发中会用到很多树状结构的数据,比如:产品的多级分类.省市区县,大多数系统也会用到类似“通用字典/数据字典”的功能, ...
- 分享基于Entity Framework的Repository模式设计(附源码)
关于Repository模式,在这篇文章中有介绍,Entity Framework返回IEnumerable还是IQueryable? 这篇文章介绍的是使用Entity Framework实现的Rep ...
- CopyOnWriteArrayList设计思路与源码分析
CopyOnWriteArrayList实现了List接口,RandomAccess,Cloneable,Serializable接口. CopyOnWriteArrayList特性 1.线程安全,在 ...
- .net平台下socket异步通讯(代码实例)
你应该知道的.net平台下socket异步通讯(代码实例) 1,首先添加两个windows窗体项目,一个作为服务端server,一个作为客户端Client 2,然后添加服务端代码,添加命名空间,界面上 ...
- Java生鲜电商平台-电商中海量搜索ElasticSearch架构设计实战与源码解析
Java生鲜电商平台-电商中海量搜索ElasticSearch架构设计实战与源码解析 生鲜电商搜索引擎的特点 众所周知,标准的搜索引擎主要分成三个大的部分,第一步是爬虫系统,第二步是数据分析,第三步才 ...
- 轻量级通信引擎StriveEngine —— C/S通信demo(2) —— 使用二进制协议 (附源码)
在网络上,交互的双方基于TCP或UDP进行通信,通信协议的格式通常分为两类:文本消息.二进制消息. 文本协议相对简单,通常使用一个特殊的标记符作为一个消息的结束. 二进制协议,通常是由消息头(Head ...
随机推荐
- 基于低代码平台(Low Code Platform)开发中小企业信息化项目
前言:中小企业信息化需求强烈,对于开发中小企业信息化项目的软件工作和程序员来说,如何根据中小企业的特点,快速理解其信息化项目的需求并及时交付项目,是一个值得关注和研讨的话题. 最近几年来,随着全球经济 ...
- flask 上传文件
flask upload 近日在学习python,接触到了flask框架,刚好客户有个需求,需要在网页上传一个python 代码的zip包,然后使用docker 容器运行这个zip里面的程序,输出结果 ...
- 获取AJAX加载的内容
1.有些网页内容使用AJAX加载,AJAX一般返回的是JSON,直接对AJAX地址进行post或get,就返回JSON数据了. 2.用抓包工具分析https://movie.douban.com/j/ ...
- Struts2学习---result结果集
这一章节主要介绍如何配置结果集,分为以下几个知识点: 结果集类型(result type) 全局结果集(global types) 动态结果集(dynamic type) 带有参数的结果集(type ...
- scala写算法-快排
快排算法很经典,今天用scala的函数式思维来整理一下并实现: def qsort(list: List[Int]):List[Int]=list match { case Nil=>Nil c ...
- ArcGIS API for JavaScript 4.2学习笔记[19] 搜索小部件——使用更多数据源
上一篇中提到,空间搜索小部件是Search这个类的实例化,作为视图的ui属性添加进去后,视图就会出现搜索框了. 这节的主体代码和上篇几乎一致,区别就在上篇提及的sources属性. 先看看结果: 由于 ...
- 写给小白的JAVA链接MySQL数据库的步骤(JDBC):
作为复习总结的笔记,我罗列了几个jdbc步骤,后边举个简单的例子,其中的try块请读者自行处理. /* * 1.下载驱动包:com.mysql.jdbc.Driver;网上很多下载资源,自己找度娘,此 ...
- vuejs实现本地数据的筛选分页
今天项目需要一份根据本地数据的筛选分页功能,好吧,本来以为很简单,网上搜了搜全是ajax获取的数据,这不符合要求啊,修改起来太费力气,还不如我自己去写,不多说直接上代码 效果图: 项目需要:点击左侧进 ...
- 推荐系统 LFM 算法的简单理解,感觉比大部分网上抄来抄去的文章好理解
本文主要是基于<推荐系统实践>这本书的读书笔记,还没有实践这些算法. LFM算法是属于隐含语义模型的算法,不同于基于邻域的推荐算法. 隐含语义模型有:LFM,LDA,Topic Model ...
- mybatis的知识点
mybatis核心配置文件的配置 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE conf ...