很久都没有写博客了,从15年4月份一直忙到现在,我才有时间去做梳理和总结,因为我提离职了,感觉整个世界突然变得不一样,随着而来的就是心情的放松,写一篇文章也是对过去一年多工作的梳理,加深印象 积累和沉淀。

因为从事的公司是建筑行业的公司,产品也是基于建筑管理体系,整体的项目包含了web端、客户端、服务端,以及因为产品功能需要的一些工具类的软件。在这种多系统的体系结构之下,我们需要进行多个系统之间的实时通讯,其实做到实时通讯的方式有很多种

1.sql server的Server_borker    数据变更通知,是基于sql server数据库的,表中的数据变更会通知到监听的那端,但是觉得考虑到通讯比较频繁,通讯端比较多,这种方式很容易造成代码上和程序上的混乱,不做考虑。

2.wcf的消息广播   相比第一种,这个对于这种多系统通讯更加不具备优势。这种在服务端进行操作,客户端通过注册来监听服务端处理的进度很明显不适合两个或者多个客户端之间的通信,我们的系统可不仅仅限于客户端服务端这么简单,不做考虑。

3..NetMQ 就是本章中要介绍的解决多系统通讯问题的杀手锏了。这个其实在最开始是我们同事去下载研究的,在之后经过一些包装可以很方便的去使用,接下来我们去一起了解一下。

下载地址:http://www.codeproject.com/Articles/193611/DotNetMQ-A-Complete-Message-Queue-System-for-NET

简单的画个图可以更加方便的去了解这个结构

通过这个图我们可以看到,在多个客户端通讯之前需要先开启服务,然后通过唯一性的token我们就可以做到客户端之间的信息通讯。

下载下来的应该是一个服务的启动程序和一个管理端,经过包装和更改更加方便使用一些:

两个服务

1..NETMQ本身的服务

2.添加令牌的服务,开放成对外的wcf接口,可以通过接口取添加令牌。

关于服务配置其实修改后只需要服务端口就行了,连接通过地址和端口号就可以连接。

最后就是令牌了,令牌就是客户端之间通讯的一个token,就是一个唯一的识别信息,就跟qq一样,给妹子发信息总要知道人家的qq号吧,token其实也可以这么理解。

客户端上线之后就客户端连接就是1。

通过上述的描述我想基本都对这个有一个印象了,通过这些印象我们可以想象到他的应用场景,比如去做一个聊天工具,做上传下载的进度提示,等等。

了解了应用场景我们就应该去想想我们怎么样才能简单而又方便的把它应用在我们的项目中,可以解决我们产品和项目中的实际问题。

服务端:

图中可以看到,我们下载下来的.NETMQ在服务端只需要引用这三个库就可以了,

MQServer就是我们针对实际项目应用做的一些修改,将服务开启、停止、令牌的添加删除以及管理都在这里做了包装,只需要去引用就可以了。

/// <summary>
/// 消息中心服务器端管理类
/// </summary>
public class MQService
{
#region 单例
private static MQService _instance; /// <summary>
/// 单例
/// </summary>
public static MQService Instance
{
get
{
if (_instance == null)
{
_instance = new MQService();
}
return _instance;
}
}
#endregion #region 字段
MDSServer server;
MDSController controller; #endregion #region 属性
/// <summary>
/// 服务是否处于开启状态
/// </summary>
public bool IsOpened { get; set; }
#endregion #region 构造方法
public MQService()
{
server = new MDSServer();
}
#endregion
#region 开启服务
/// <summary>
/// 开启服务
/// </summary>
public void Start()
{
try
{
server.Start();
IsOpened = true;
controller = new MDS.Management.MDSController(AppConfig.Config.MessageServiceIP, AppConfig.Config.MessageServicePort);
controller.Connect();
}
catch (Exception ex)
{
throw ex;
}
}
#endregion #region 关闭服务
/// <summary>
/// 关闭服务
/// </summary>
public void Stop()
{
try
{
if (IsOpened)
{
server.Stop(true);
IsOpened = false;
controller.Disconnect();
}
}
catch (Exception ex)
{
throw ex;
}
}
#endregion #region 添加令牌
public bool AddToken(string token)
{
try
{
controller.SendMessage(
new AddNewApplicationMessage
{
ApplicationName = token
});
return true;
}
catch
{
return false;
}
}
#endregion
#region 删除令牌
public void RemoveToken(string token)
{
var message = controller.SendMessageAndGetResponse(
new RemoveApplicationMessage
{
ApplicationName = token
});
}
#endregion
#region 获取令牌列表
public ObservableCollection<TokenClass> GetTokenList()
{
ObservableCollection<TokenClass> result = new ObservableCollection<TokenClass>();
//Send a message to MDS server to get list of client applications, get response and fill data grid.
var message = controller.SendMessageAndGetResponse(new GetApplicationListMessage());
if (message.MessageTypeId != ControlMessageFactory.MessageTypeIdGetApplicationListResponseMessage)
{
throw new MDSException("Response message to GetApplicationListMessage must be a GetApplicationListResponseMessage");
} var applicationListMessage = message as GetApplicationListResponseMessage;
if (applicationListMessage == null)
{
throw new MDSException("Incorrect message type. MessageTypeId = " + message.MessageTypeId + ", but Type of object: " + message.GetType().Name);
}
MDS.Communication.Messages.ControllerMessages.GetApplicationListResponseMessage.ClientApplicationInfo[] applications = applicationListMessage.ClientApplications;
foreach (var application in applications)
{
TokenClass tc = new TokenClass();
tc.TokenName = application.Name;
tc.TokenConnect = application.CommunicatorCount;
result.Add(tc);
}
return result;
}
#endregion
}

服务端简单的使用就是这些,详细的介绍以及内部原理网上很多,这里就不介绍了。

客户端:

关于客户端呢,为了便于更方便的使用我写一个简单的demo去演示一下。

图中红框的部分其实就是MDSCommonLib这个库,下面几个类就是对外的事件和方法的包装,我们可以看一下代码:

public class MQMessage
{
CommunicationClient client; public readonly static MQMessage Instance = new MQMessage();
public MQMessage()
{
//FileTransfer.BLL.XmlReader.ReadXmlInfo();
client = new CommunicationClient();
client.OnMessageReceived += client_OnMessageReceived;
client.OnResponseMessageReceived += client_OnResponseMessageReceived;
}
/// <summary>
/// 接收消息事件
/// </summary>
public event EventHandler OnMessageReceived; /// <summary>
/// 接收消息回执事件
/// </summary>
public event EventHandler OnResponseMessageReceived;
/// <summary>
/// 接收消息事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void client_OnResponseMessageReceived(object sender, MessageReceiveEventArgs e)
{
if (OnResponseMessageReceived != null)
{
OnResponseMessageReceived(sender, e);
}
}
/// <summary>
/// 接收消息回执事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void client_OnMessageReceived(object sender, MessageReceiveEventArgs e)
{
if (OnMessageReceived != null)
{
OnMessageReceived(sender, e);
}
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="messageContent"></param>
public void SendMessage(string messageContent, string tokenName)
{
client.SendMessage(messageContent, tokenName);
}
/// <summary>
/// 开启服务
/// </summary>
public void Start(string tokenName)
{
client.StartConnection("127.0.0.1", , tokenName);
} /// <summary>
/// 关闭服务
/// </summary>
public void Stop()
{
client.StopConnection();
}
}

这是最外层的包装,通过这些就可以去调用

MQClientLib.MQMessage.Instance.Start("User_Sean");

客户端开启连接的方式仅仅这样就可以了,通过这行表示:User_Sean上线了。

这样我们在服务端就可以看到User_Sean的连接:

呐,这是一个客户端,如果是多个客户端连接上了呢? 我们就可以通过

/// <summary>
/// 发送消息
/// </summary>
/// <param name="messageContent"></param>
public void SendMessage(string messageContent, string tokenName)
{
client.SendMessage(messageContent, tokenName);
}

调用这行代码去向其它客户端发送信息,其它客户端接收到信息的时候也会触发这边的回执事件。

/// <summary>
/// 接收消息回执事件
/// </summary>
public event EventHandler OnResponseMessageReceived;

通过注册这个事件,在对方接收到你发送的消息的时候,可以触发这个事件。


/// <summary>
/// 接收消息事件
/// </summary>
public event EventHandler OnMessageReceived;

 

这个是用来接收别人给你发送的信息的,信息通过这个时间的sender传递过来。

使用暂时就这些,因为代码是加密的,所以只能以后去重新做一下然后给各位提供下载地址了。

当然,关于mq的使用dotNetMQ只是其中一项,今天介绍的也只是通讯,之后下一篇博客会介绍相关的msmq、queue等等,后面精彩继续~~~~~

多系统通讯-DotNetMQ的更多相关文章

  1. 【翻译】DotNetMQ: 一个.NET版完整的消息队列系统

    在一个大型的分布式系统中,消息队列是不可缺少的中间件,能很好的解决异步消息.应用解耦.均衡并发等问题.在.net中,偶然发现一个效率不错.安全可靠.功能齐全的消息组件,忍不住翻译过来,供大家快速预览. ...

  2. Windows Azure Service Bus Topics实现系统松散耦合

    前言 Windows Azure中的服务总线(Service Bus)提供了多种功能, 包括队列(Queue), 主题(Topic),中继(Relay),和通知中心(Notification Hub) ...

  3. 用WidgeDuino创建一个SCADA(监控与数据採集)系统

    WidgeDuino – 近期在Kickstarter上亮相 – 是一个智能的易配置的窗体- 基于Microsoft Windows平台和基于像 Atmel-based Arduino board 的 ...

  4. 开源消息中间件DotNetMQ

    由于这个开源项目对我这种中间件菜鸟很有帮助,因此,我将官方的说明文档翻译如下: Introduction In this article, I will introduce a new and ind ...

  5. IM-即时通讯技术概述

    IM-即时通讯技术概述 简述 即时通讯技术(IM)支持用户在线实时交谈.如果要发送一条信息,用户需要打开一个小窗口,以便让用户及其朋友在其中输入信息并让交谈双方都看到交谈的内容.大多数常用的即时通讯发 ...

  6. web前端工程师在移动互联网时代里的地位问题 为啥C/S系统在PC端没有流行起来,却在移动互联网下流行了起来 为啥移动端的浏览器在很多应用里都是靠边站,人们更加倾向于先麻烦自己一下,下载安装个客户端APP

    web前端工程师在移动互联网时代里的地位问题 支付宝十周年推出了一个新产品:支付宝的十年账单,我也赶个时髦查看了一下我的支付宝十年账单,哎,感慨自己真是太屌丝了,不过这只是说明我使用淘宝少了,当我大规 ...

  7. 消息通讯之关于消息队列MQ必须了解的相关概念

    目录 系统通讯方式有哪些? 消息队列的应用场景 消息队列通讯模型 常见的消息协议 AMQP MQTT ATOMP JMS 小结 系统通讯方式有哪些? RPC调用 RPC 全称 Remote Proce ...

  8. linux 让程序在后台运行的几种可靠方法

    我们经常会碰到这样的问题,用 telnet/ssh 登录了远程的 Linux 服务器,运行了一些耗时较长的任务, 结果却由于网络的不稳定导致任务中途失败.如何让命令提交后不受本地关闭终端窗口/网络断开 ...

  9. LoadRunner培训初级教程

    一 LoadRunner简介 1.1 Loadrunner介绍 LoadRunner 是 HP Mercury Interactive 用来测试应用程序性能的工具  LoadRunner 通过模拟一个 ...

随机推荐

  1. XUtils框架的学习(一)

    一  xutils框架引入到AndroidStudio工程,最简单的方法:① 在APP的build.gradle里面加入 compile 'org.xutils:xutils:3.3.36'.② 一定 ...

  2. u-boot向linux内核传递启动参数(详细)

    U-BOOT 在启动内核时,会向内核传递一些参数.BootLoader 可以通过两种方法传递参数给内核,一种是旧的参数结构方式(parameter_struct),主要是 2.6 之前的内核使用的方式 ...

  3. JqueryTips小实验,浏览器滚动条不限制

    最近做公司的项目有些地方可能需要一些小提示,于是自己建立项目研究tips.在此之前看到过一些别人写的JqueryTips,于是借鉴了一些别人的经验在此基础上我做出了一些改进. 有的同学可能使用过其他一 ...

  4. javascript设计模式7

    链式调用 (function(){ function _$(els){ //... } _$.prototype={ each:function(fn){ for(var i=0,len=this.e ...

  5. MySQL UNION 与 UNION ALL 语法与用法

    MySQL UNION 语法 MySQL UNION 用于把来自多个 SELECT 语句的结果组合到一个结果集合中.语法为: SELECT column,... FROM table1 UNION [ ...

  6. 关于C#动态调用VC Dll的方法(转)

    http://blog.csdn.net/null1/article/details/3953155

  7. C++&OpenCV中读取灰度图像到数组的两种

    如标题所言,此处是对于灰度图像而言 ///method 1 read the image data one by one for (int row = 0, i = 0;row < imgDst ...

  8. 你可能没听过的 Java 8 中的 10 个特性

    你以前听到的谈论关于Java8的所有都是围绕lambda表达式. 但它仅仅是Java8的一部分. Java 8 有许多新特性—一些强大的新类和语法, 还有其他的从一开始就应该具有的东西. 我将要介绍我 ...

  9. (原创)vagrant up 异常报错,出现 There was an error while executing `VBoxManage` 的解决方法

    最近在使用 vagrant homestead 时,不小心在虚拟机上使用了 exit 命令退出虚拟机,导致再使用 vagrant up 时出现以下错误: Bringing machine 'larav ...

  10. innobackupex 单脚本循环7天一全备6增备脚本更新

    #!/bin/bash #日期转为天数 function date2days { echo "$*" | awk '{ z=-$)/); y=$+-z; m=$+*z-; j=*m ...