第一部分引用于:点击打开

1:简单介绍

PUB-SUB模式一般处理的都不是系统的关键数据。发布者不关注订阅者是否收到发布的消息,订阅者也不知道自己是否收到了发布者发出的所有消息。你也不知道订阅者何时开始收到消息。类似于广播,收音机。因此逻辑上,它都不是可靠的。这个可以通过与请求响应模型组合来解决。


图1:简单的发布订阅模式


图2:与请求响应模式组合的发布订阅模式

2:案例

定义IPublishser接口

namespace NetMQDemoPublisher
{
public interface IPublisher:IDisposable
{
/// <summary>
/// 发布消息
/// </summary>
/// <param name="topicName">主题</param>
/// <param name="data">内容</param>
void Publish(string topicName, string data);
}
}

Publisher实现类

namespace NetMQDemoPublisher
{
public class Publisher:IPublisher
{
private object _lockObject = new object(); private PublisherSocket _publisherSocket; public Publisher(string endPoint)
{
_publisherSocket = new PublisherSocket();
_publisherSocket.Options.SendHighWatermark = ;
_publisherSocket.Bind(endPoint);
}
#region Implementation of IDisposable /// <summary>
/// 执行与释放或重置非托管资源相关的应用程序定义的任务。
/// </summary>
public void Dispose()
{
lock (_lockObject)
{
_publisherSocket.Close();
_publisherSocket.Dispose();
}
} /// <summary>
/// 发布消息
/// </summary>
/// <param name="topicName">主题</param>
/// <param name="data">内容</param>
public void Publish(string topicName, string data)
{
lock (_lockObject)
{
_publisherSocket.SendMoreFrame(topicName).SendFrame(data);
}
} #endregion
}
}

Publisher窗口界面

界面中实现的功能代码

namespace NetMQDemoPublisher
{
public partial class PublisherForm : Form
{
private IPublisher publisher;
public PublisherForm()
{
InitializeComponent();
publisher = new Publisher("tcp://127.0.0.1:8888");
} private void button1_Click(object sender, EventArgs e)
{
string strContent = textBox1.Text;
ListViewItem item = new ListViewItem(string.Format("topic:NetMQ,Data:{0}", strContent));
listView1.Items.Add(item);
publisher.Publish("NetMQ", strContent);
}
}
}

定义ISubscriber接口

namespace NetMQDemoSubscriber
{
public interface ISubscriber:IDisposable
{
/// <summary>
/// 事件
/// </summary>
event Action<string, string> Nofity; /// <summary>
/// 注册订阅主题
/// </summary>
/// <param name="topics"></param>
void RegisterSubscriber(List<string> topics); /// <summary>
/// 注册订阅
/// </summary>
void RegisterSbuscriberAll(); /// <summary>
/// 移除所有订阅消息,并关闭
/// </summary>
void RemoveSbuscriberAll();
}
}

Subscriber实现类

namespace NetMQDemoSubscriber
{
public class Subscriber:ISubscriber
{
private SubscriberSocket _subscriberSocket = null;
private string _endpoint = @"tcp://127.0.0.1:9876"; public Subscriber(string endPoint)
{
_subscriberSocket = new SubscriberSocket();
_endpoint = endPoint;
}
#region Implementation of IDisposable /// <summary>
/// 执行与释放或重置非托管资源相关的应用程序定义的任务。
/// </summary>
public void Dispose()
{
throw new NotImplementedException();
} #endregion #region Implementation of ISubscriber public event Action<string, string> Nofity = delegate { }; /// <summary>
/// 注册订阅主题
/// </summary>
/// <param name="topics"></param>
public void RegisterSubscriber(List<string> topics)
{
InnerRegisterSubscriber(topics);
} /// <summary>
/// 注册订阅
/// </summary>
public void RegisterSbuscriberAll()
{
InnerRegisterSubscriber();
} /// <summary>
/// 移除所有订阅消息,并关闭
/// </summary>
public void RemoveSbuscriberAll()
{
InnerStop();
} #endregion #region 内部实现 /// <summary>
/// 注册订阅消息
/// </summary>
/// <param name="topics">订阅的主题</param>
private void InnerRegisterSubscriber(List<string> topics = null)
{
InnerStop();
_subscriberSocket = new SubscriberSocket();
_subscriberSocket.Options.ReceiveHighWatermark = ;
_subscriberSocket.Connect(_endpoint);
if (null == topics)
{
_subscriberSocket.SubscribeToAnyTopic();
}
else
{
topics.ForEach(item => _subscriberSocket.Subscribe(item));
}
Task.Factory.StartNew(() =>
{
while (true)
{
string messageTopicReceived = _subscriberSocket.ReceiveFrameString();
string messageReceived = _subscriberSocket.ReceiveFrameString();
Nofity(messageTopicReceived, messageReceived);
}
});
} /// <summary>
/// 关闭订阅
/// </summary>
private void InnerStop()
{
_subscriberSocket.Close();
} #endregion
}
}

Subscriber窗口界面

窗体功能代码

namespace NetMQDemoSubscriber
{
public partial class SubscriberForm : Form
{
private ISubscriber subscriber;
public SubscriberForm()
{
InitializeComponent();
} private void SubscriberForm_Load(object sender, EventArgs e)
{
subscriber = new Subscriber("tcp://127.0.0.1:8888");
subscriber.RegisterSbuscriberAll();
subscriber.Nofity+= delegate(string s, string s1)
{
ListViewItem item = new ListViewItem(string.Format("topic:{0},Data:{1}", s, s1));
listView1.Items.Add(item);
};
}
}
}

运行后,Publiser开启一个,Subscirber开启三个,进行测试如图

源码下载

如果觉得文章好,记得关注一下公众号哟!

NetMQ 发布订阅模式 Publisher-Subscriber的更多相关文章

  1. NetMQ(三): 发布订阅模式 Publisher-Subscriber

    ZeroMQ系列 之NetMQ 一:zeromq简介 二:NetMQ 请求响应模式 Request-Reply 三:NetMQ 发布订阅模式 Publisher-Subscriber 四:NetMQ ...

  2. java 多线程 发布订阅模式:发布者java.util.concurrent.SubmissionPublisher;订阅者java.util.concurrent.Flow.Subscriber

    1,什么是发布订阅模式? 在软件架构中,发布订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者).而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话 ...

  3. NetMQ发布订阅C#示例

    NetMQ (ZeroMQ to .Net),ØMQ号称史上最快中间件.它对socket通信进行了封装,使得我们不需要写socket函数调用就能完成复杂的网络通信.和一般意义上的消息队列产品不同的是, ...

  4. redis的发布订阅模式pubsub

    前言 redis支持发布订阅模式,在这个实现中,发送者(发送信息的客户端)不是将信息直接发送给特定的接收者(接收信息的客户端),而是将信息发送给频道(channel),然后由频道将信息转发给所有对这个 ...

  5. 观察者模式 vs 发布-订阅模式

    我曾经在面试中被问道,_“观察者模式和发布订阅模式的有什么区别?” _我迅速回忆起“Head First设计模式”那本书: 发布 + 订阅 = 观察者模式 “我知道了,我知道了,别想骗我” 我微笑着回 ...

  6. js设计模式之发布/订阅模式模式

    一.前言 发布订阅模式,基于一个主题/事件通道,希望接收通知的对象(称为subscriber)通过自定义事件订阅主题,被激活事件的对象(称为publisher)通过发布主题事件的方式被通知. 就和用户 ...

  7. js设计模式-发布/订阅模式

    一.前言 发布订阅模式,基于一个主题/事件通道,希望接收通知的对象(称为subscriber)通过自定义事件订阅主题,被激活事件的对象(称为publisher)通过发布主题事件的方式被通知. 就和用户 ...

  8. js之观察者模式和发布订阅模式区别

    观察者模式(Observer) 观察者模式指的是一个对象(Subject)维持一系列依赖于它的对象(Observer),当有关状态发生变更时 Subject 对象则通知一系列 Observer 对象进 ...

  9. 观察者模式Vs发布订阅模式

    1)观察者模式 观察者模式通俗的讲就是我们平事件调用(click/change等等) 大家先看这个图片.我们被观察者Subject(监听某个事件)发生改变时,观察者Observer监听到没改变做出调整 ...

随机推荐

  1. Python:每日一题001

    题目:有四个数字:1.2.3.4,能组成多少个互不相同且无重复数字的三位数?各是多少? **程序分析:可填在百位.十位.个位的数字都是1.2.3.4.组成所有的排列后再去 掉不满足条件的排列. 个人解 ...

  2. Oracle中为表设置自动增长的标识列

    -- Create sequence create sequence INNERID minvalue 1 maxvalue 99999999999999 start with 1 increment ...

  3. centos7下载

    http://archive.kernel.org/centos-vault/7.0.1406/isos/x86_64/

  4. tensorflow学习之(二)Seesion的两种打开模式

    #Seesion的两种打开模式 import tensorflow as tf matrix1 = tf.constant([[3,3]])#一行两列的一个矩阵 matrix2 = tf.consta ...

  5. CentOs7安装PHP

    来源:https://jingyan.baidu.com/article/2d5afd692df18d85a3e28e4c.html 一.下载源码 1.cd /usr/local/src/ 2. 执行 ...

  6. vue报错TypeError: Cannot read property '$createElement' of undefined

    报错截图: 这个错误就是路由上的component写成了components

  7. Android 各种常见activity

    引用:Activity初学乍练 //1.拨打电话 // 给移动客服10086拨打电话 Uri uri = Uri.parse("tel:10086"); Intent intent ...

  8. 20154305 齐帅 PC平台逆向破解

    Exp1 PC平台逆向破解 一.实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. 该程序同时 ...

  9. volatile和synchronized

    volatile是变量修饰符,而synchronized则作用于一段代码或方法:看如下三句get代码: int i1;              int geti1() {return i1;} vo ...

  10. Hadoop 综合揭秘——HBase的原理与应用

    前言 现今互联网科技发展日新月异,大数据.云计算.人工智能等技术已经成为前瞻性产品,海量数据和超高并发让传统的 Web2.0 网站有点力不从心,暴露了很多难以克服的问题.为此,Google.Amazo ...