zeromq --- 第二篇

第二种模式是数据分发,即服务端推送消息到一组客户端,让我们看一下天气预报是如何推送天气信息,其       
信息内容包括地区,温度和湿度等信息,我们将生成随机数据,如天气信息:       
       
这是server端程序,我们使用5556这个端口       
       
//  Weather update server       
//  Binds PUB socket to tcp://*:5556       
//  Publishes random weather updates       
       
#include "zhelpers.h"       
       
int main (void)       
{       
    //  Prepare our context and publisher       
    void *context = zmq_ctx_new ();       
    void *publisher = zmq_socket (context, ZMQ_PUB);       
    int rc = zmq_bind (publisher, "tcp://*:5556");       
    assert (rc == 0);       
       
    //  Initialize random number generator       
    srandom ((unsigned) time (NULL));       
    while (1) {       
        //  Get values that will fool the boss       
        int zipcode, temperature, relhumidity;       
        zipcode     = randof (100000);       
        temperature = randof (215) - 80;       
        relhumidity = randof (50) + 10;       
       
        //  Send message to all subscribers       
        char update [20];       
        sprintf (update, "%05d %d %d", zipcode, temperature, relhumidity);       
        s_send (publisher, update);       
    }       
    zmq_close (publisher);       
    zmq_ctx_destroy (context);       
    return 0;       
}       
       
对于更新消息包流没有开头和结束,像一个无终止的广播;       
       
这个是客户端,它会监听到更新包流,并获取其所关心的地区的消息;例如纽约市       
       
       
//  Weather update client       
//  Connects SUB socket to tcp://localhost:5556       
//  Collects weather updates and finds avg temp in zipcode       
       
#include "zhelpers.h"       
       
int main (int argc, char *argv [])       
{       
    //  Socket to talk to server       
    printf ("Collecting updates from weather server…\n");       
    void *context = zmq_ctx_new ();       
    void *subscriber = zmq_socket (context, ZMQ_SUB);       
    int rc = zmq_connect (subscriber, "tcp://localhost:5556");       
    assert (rc == 0);       
       
    //  Subscribe to zipcode, default is NYC, 10001       
    char *filter = (argc > 1)? argv [1]: "10001 ";       
    rc = zmq_setsockopt (subscriber, ZMQ_SUBSCRIBE,       
                         filter, strlen (filter));       
    assert (rc == 0);       
       
    //  Process 100 updates       
    int update_nbr;       
    long total_temp = 0;       
    for (update_nbr = 0; update_nbr < 100; update_nbr++) {       
        char *string = s_recv (subscriber);       
       
        int zipcode, temperature, relhumidity;       
        sscanf (string, "%d %d %d",       
            &zipcode, &temperature, &relhumidity);       
        total_temp += temperature;       
        free (string);       
    }       
    printf ("Average temperature for zipcode '%s' was %dF\n",       
        filter, (int) (total_temp / update_nbr));       
       
    zmq_close (subscriber);       
    zmq_ctx_destroy (context);       
    return 0;       
}       

233357_FKCe_2413521.png

 

 

注意当你使用SUB套接字的时候,你必须使用zmq_setsockopt()和SUBSCRIBE进行订阅设置,       
如果你不进行此设置,你将一无所获;对于新手,这是一个经常犯的错误;       
订阅者可以设置很多订阅,如果一个更新信息匹配任何一个,订阅者就会收到该消息;订阅者       
也可以取消某个订阅,订阅信息不一定是一个可见的字符串,可以参考zmq_setsockopt()来       
看看他是如何工作的;       
       
PUB-SUB模式是异步的,客户端循环调用zmq_recv(),如果试图发送一个消息给SUB套接口,则       
会导致一个错误;类似的,服务端会根据需要调用zmq_send(),但是不一定会在PUB套接口上调用zmq_recv;       
       
理论上,使用zeromq套接字,不用关心哪一侧连接,哪一侧绑定;实际上也并没有什么不同;       
所以,绑定PUB,连接SUB,除非你的网络设计这种方式行不通;       
       
对于PUB-SUB模式来说,还有一件重要的事情,你无法预测何时订阅者会接收消息,即使你启动       
一个订阅者, 等待一会,然后启动发布者,订阅者总会丢失发布者发送的第一个消息,这是因为       
当订阅者连接到发布者时(这会消耗点时间),发布者可能已将消息发送出去;       
       
这种 "slow joiner"我们之后会详细讨论,记住一点,zeromq是异步io,也就是说,你有两个       
节点干这件事情,按找这个顺序:       
       
订阅者连接到一个端点,接收和计数消息       
发布者绑定到一个端点,并立即发送1000个消息       
       
然后订阅者极有可能没有收到消息,或许你会确定下正确的设置并继续尝试,订阅者依旧未能       
收到消息;       
       
tcp的握手会消耗几毫秒,这依赖于你的网络以及两个端点之间的跳数,这时,zeromq可以发送       
好多消息;假定,建立连接会耗费5毫秒,那么每秒钟将处理1M个消息,在这5毫秒中,订阅者       
会连接发布者,发布者会每1毫秒发送1K个消息;       
       
       
在第二章中,我们将讨论如何同步订阅者和发布者,以便直到待订阅者准备好,发布者才发布数据;       
不过,延迟发布是一件很蠢的事情,在应用程序中,不要这样做,这是很不雅的很脆弱的,       
并且低效的,到第二章我们会知道如何处理是正确的;       
       
订阅者接收其区域的100个数据包,这就意味着从服务器发送10M个消息包,如果是随机发布的话;       
你可以先启动客户端,然后再启动服务端,客户端会继续工作;你可以随心所欲的启动服务端,客户端       
也会照常工作,当客户端收集够100个消息包的时候,就会计算打印这些数据,然后退出;       
       
关于订阅-发布模式       
       
一个订阅者可以每次使用一个连接来连接多个发布者,数据通道是双向的,所以发布者       
不会互相干扰;       
       
如果发布者没有订阅者连接,他会丢弃所有的消息;       
       
如果你使用tcp,订阅者会比较慢,消息会在发布端依次排序,后续我们会看到如何使用“高水位”       
来保护发布者;       
       
在zeromq的3.x版本中,当使用(tcp:// or ipc://)协议时,发布端会进行过滤;使用epgm://        
协议,订阅端会进行过滤;在 ZeroMQ v2.x版本中on个,两侧都会进行过滤;       
       
这是在我笔记本中测试的接收和过滤10M消息的耗时,配置为 Intel i5       
       
       
$ time wuclient       
Collecting updates from weather server...       
Average temperature for zipcode '10001 ' was 28F       
       
real    0m4.470s       
user    0m0.000s       
sys     0m0.008s       
       

 


 

转载于:https://my.oschina.net/u/2413521/blog/546429

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值