.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 ...
随机推荐
- .NET Core 2.0下载和文档
.NET Core 2.0 RTM 正式版2017/8/14 发布.对应发布 ASP.NET Core 2.0 .EF Core 2.0以及.NET Standard 2.0. 你可以通过 Visua ...
- activeMq 使用方法
一:activeMq介绍 ActiveMQ是一种开源的,实现了JMS1.1规范的,面向消息(MOM)的中间件,为应用程序提供高效的.可扩展的.稳定的和安全的企业级消息通信,下载地址是:http://a ...
- springboot+jpa+thymeleaf增删改查的示例(转)
这篇文章介绍如何使用jpa和thymeleaf做一个增删改查的示例. 先和大家聊聊我为什么喜欢写这种脚手架的项目,在我学习一门新技术的时候,总是想快速的搭建起一个demo来试试它的效果,越简单越容易上 ...
- 「mysql优化专题」90%程序员面试都用得上的索引优化手册(5)
目录(技术文) 多关于索引,分为以下几点来讲解: 一.索引的概述(什么是索引,索引的优缺点) 二.索引的基本使用(创建索引) 三.索引的基本原理(面试重点) 四.索引的数据结构(B树,hash) 五. ...
- Intellij IDEA更新SVN没有提示语
更新SVN时IDE下方没有提示语句 解决方法: 点击编辑器右下方的 Event Log 按钮 打开 Show balloons 就可以显示了.
- 17089 最大m子段和
17089 最大m子段和 时间限制:1000MS 内存限制:65535K提交次数:0 通过次数:0 题型: 编程题 语言: G++;GCC;VC Description "最大m子段和 ...
- 重温javascript数据类型
在javaScript中,有五种简单的数据类型,分别是 Undefined Null Boolean Number String 还有一种复杂的数据类型object,object本质是有一组无序的名值 ...
- 使用jQuery制作一个简易的购物车结算流程
因为今天下午时候在网上买了东西,在结算界面的时候突发奇想的也想自己动手做一个结算界面,当然了,只是一个最简易的结算界面,有商品数量的加减,有单价和小计,单个多个删除,全选和区县全选等等一些小功能,我在 ...
- Git详解之九:Git内部原理
Git 内部原理 不管你是从前面的章节直接跳到了本章,还是读完了其余各章一直到这,你都将在本章见识 Git 的内部工作原理和实现方式.我个人发现学习这些内容对于理解 Git 的用处和强大是非常重要的, ...
- CSS3背景渐变。。。
CSS3 Gradient 分为 linear-gradient(线性渐变)和 radial-gradient(径向渐变).而我们今天主要是针对线性渐变来剖析其具体的用法.为了更好的应用 CSS3 G ...