文档章节

zeromq -- 第一篇 初识zeromq

zhongyuansunlei
 zhongyuansunlei
发布于 2015/12/16 21:14
字数 1553
阅读 76
收藏 1

前言        
        
千言万语zeromq        
        
zeromq(0mq,或者zmq)看起来像一个嵌入式的网络库文件,但其功能如同一个并发框架;        
它提供了能够携带原子消息的套接字,可以实现进程内部,进程间,tcp以及多播通信;你        
可以使用诸如fan-out,pub-sub,任务分发以及请求响应等模式来连接套接口N-to-N;        
对于集群软件而言,它的效率非常高;它的异步IO模式可以提供可扩展的多核应用;同时,        
其提供多种语言的API,可以运行在绝大多数的操作系统上;zeromq是imatix公司开发的,        
是一款LGPLv3 的开源软件;        
        
        
开始        
        
        
先从hello world 这个程序开始来,服务端监听5555端口,当它接收到客户端的hello时,        
将会回复一个world给客户端;        
        
请求-响应 对套接字;客户端先调用 zmq_send() 然后调用 zmq_recv(),类似的服务端调用        
zmq_recv(),然后调用zmq_send()函数;下列为其参考语言:        
        
//        
//  Hello World server in C++        
//  Binds REP socket to tcp://*:5555        
//  Expects "Hello" from client, replies with "World"        
//        
#include <zmq.hpp>        
#include <string>        
#include <iostream>        
#ifndef _WIN32        
#include <unistd.h>        
#else        
#include <windows.h>        
        
#define sleep(n)    Sleep(n)        
#endif        
        
int main () {        
    //  Prepare our context and socket        
    zmq::context_t context (1);        
    zmq::socket_t socket (context, ZMQ_REP);        
    socket.bind ("tcp://*:5555");        
        
    while (true) {        
        zmq::message_t request;        
        
        //  Wait for next request from client        
        socket.recv (&request);        
        std::cout << "Received Hello" << std::endl;        
        
        //  Do some 'work'        
        sleep(1);        
        
        //  Send reply back to client        
        zmq::message_t reply (5);        
        memcpy ((void *) reply.data (), "World", 5);        
        socket.send (reply);        
    }        
    return 0;        
}        
      hwserver.cpp  
可以看到zeromq的语言非常类似c和c++语言,使用java或php语言,其代码将更加简单:        
        
<?php        
/*        
*  Hello World server        
*  Binds REP socket to tcp://*:5555        
*  Expects "Hello" from client, replies with "World"        
* @author  Ian Barber <ian(dot)barber(at)gmail(dot)com>        
*/        
        
$context = new ZMQContext(1);        
        
//  Socket to talk to clients        
$responder = new ZMQSocket($context, ZMQ::SOCKET_REP);        
$responder->bind("tcp://*:5555");        
        
while (true) {        
    //  Wait for next request from client        
    $request = $responder->recv();        
    printf ("Received request: [%s]\n", $request);        
        
    //  Do some 'work'        
    sleep (1);        
        
    //  Send reply back to client        
    $responder->send("World");        
}        
      hwserver.php  
        
//        
//  Hello World server in Java        
//  Binds REP socket to tcp://*:5555        
//  Expects "Hello" from client, replies with "World"        
//        
        
import org.zeromq.ZMQ;        
        
public class hwserver {        
        
    public static void main(String[] args) throws Exception {        
        ZMQ.Context context = ZMQ.context(1);        
        
        //  Socket to talk to clients        
        ZMQ.Socket responder = context.socket(ZMQ.REP);        
        responder.bind("tcp://*:5555");        
        
        while (!Thread.currentThread().isInterrupted()) {        
            // Wait for next request from the client        
            byte[] request = responder.recv(0);        
            System.out.println("Received Hello");        
        
            // Do some 'work'        
            Thread.sleep(1000);        
        
            // Send reply back to client        
            String reply = "World";        
            responder.send(reply.getBytes(), 0);        
        }        
        responder.close();        
        context.term();        
    }        
}        
        
      hwserver.java  
        
c++客户端程序如下所示:        
        
//  Hello World client        
#include <zmq.h>        
#include <string.h>        
#include <stdio.h>        
#include <unistd.h>        
        
int main (void)        
{        
    printf ("Connecting to hello world server…\n");        
    void *context = zmq_ctx_new ();        
    void *requester = zmq_socket (context, ZMQ_REQ);        
    zmq_connect (requester, "tcp://localhost:5555");        
        
    int request_nbr;        
    for (request_nbr = 0; request_nbr != 10; request_nbr++) {        
        char buffer [10];        
        printf ("Sending Hello %d…\n", request_nbr);        
        zmq_send (requester, "Hello", 5, 0);        
        zmq_recv (requester, buffer, 10, 0);        
        printf ("Received World %d\n", request_nbr);        
    }        
    zmq_close (requester);        
    zmq_ctx_destroy (context);        
    return 0;        
}        
        
        
        
这看起来非常的简单,但是zeromq还有更强大的功能;你可以一次性的向服务端发数以万计        
的客户端,它仍然会快速的处理;试着启动客户端然后启动服务端,来看看他是如何工作的;        
然后再思考下;        
        
如果你杀掉一个服务端,然后重启他,客户端将不会完全恢复;从当掉的进程恢复不是一件        
容易的事情;创建一个可靠的请求-响应工作流是非常复杂的,不过第四章的可靠的请求-响应        
模式可以解决他;        
        
这种场景下背后发生的事情总是会引起我们的注意,例如如何让代码更简洁,如何让代码更不容易        
当掉,即使在高负荷情况下;这就是请求-响应模式,或许是使用zeromq的最简单的方式,        
其类同于rpc调用或者客户端/服务端;        
        
        
如果你不告诉zeromq消息大小,zeromq是不会知道这些数据的;这就意味着,你必须安全的格式化        
数据,以便应用程序可以读取;对于对象或者复杂的数据来说这确实是一个工作量,就像Protocol Buffers        
但是对于字符串来说,你得小心点;        
        
在c语言中,字符串是以null来结束的;我们可以发送一个“hello”外加一个null字符;        
        
 zmq_send (requester, "Hello", 6, 0);       
        
然而,如果你用其他语言发送,可能不会包含一个null字符,例如我们用phython,        
        
 socket.send ("Hello")       
        
发送的字符将只有5个;        
        
如果你用c语言读取,你可能获取一个像字符串的东东,如果你幸运的话,可能收到的如发送的一样;        
如果客户端和服务端没有对此字符串格式达成协议,你很可能获得一个很尴尬的结果;        
        
如果你从zeromq(C语言)接收字符串,你可能无法相信它是安全终止结束的;每一次读取字符串,        
会为额外的字符申请空间,复制字符串,并在该字符串后添加null字符;        
        
我们制定一个这样的规则,zeromq字符串是由描述长度的,不需要后缀null字符的;按照最简单的例子        
zeromq字符串可以映射为一个消息帧,如同上面描述的长度和字符;        
        
c语言的代码如下所示:        
        
//  Receive ZeroMQ string from socket and convert into C string        
//  Chops string at 255 chars, if it's longer        
static char *        
s_recv (void *socket) {        
    char buffer [256];        
    int size = zmq_recv (socket, buffer, 255, 0);        
    if (size == -1)        
        return NULL;        
    if (size > 255)        
        size = 255;        
    buffer [size] = 0;        
    return strdup (buffer);        
}        

这种方式符合恰当的重复使用的精神,然后我们可以写出zeromq的send函数;这就是zhelpers.h        
文件,这可以让我们用c语音编写更短的zeromq的程序;不过,这确实有相当大的代码量,不过        
对于c程序员而言,就只当消遣了; 、

 

版本控制

由于 zeromq的版本更新也较为频繁;如果你遇到bug,可先在较新版本中查看是否已经修正,所以你最好知道
你在使用哪些版本;

#include <zmq.h>

int main (void)
{
int major, minor, patch;
zmq_version (&major, &minor, &patch);
printf ("Current 0MQ version is %d.%d.%d\n", major, minor, patch);
return 0;
}

      
 

© 著作权归作者所有

上一篇: zeromq --- 第二篇
下一篇: DES加密算法详解
zhongyuansunlei
粉丝 0
博文 5
码字总数 10078
作品 0
私信 提问
[架构] ZeroMQ 深度探索(一)

序 最初认识 ZeroMQ 是被它的名号所吸引,最近在一个高性能中间件的项目中用到了 ZeroMQ,对这个号称“史上最快的消息队列”有了更深层次的了解。如果我们仅仅把 ZeroMQ 看作是一个消息队列,...

长平狐
2013/07/01
8.1K
0
[架构] ZeroMQ 深度探索(二)

在上一篇《 ZeroMQ 深度探索(一)》中,我们使用 ZeroMQ 完成了基本的“请求-响应”模式,这个例子是基于 TCP 协议的,用法和原生的 Socket API 也差不多,都是“初始化、绑定或连接、发送、...

长平狐
2013/07/01
6.7K
2
高性能的通讯库-zeroMQ的几个高性能特征

这两天研究了一下zeroMQ,号称史上最好的通讯库,比rabbitMQ快很多,基于c语言开发的,实时流处理sorm的task之间的通信就是用的zeroMQ。 zeroMQ在使用模式上支持多种,有req-reply,publish...

天下杰论
2014/10/08
515
0
ZeroMQ学习:window下编译zeromq-3.2.3和jzmq-master

最近发现公司项目中用的activemq队列总出现这样那样的问题,可能没有相关告诉解决,很是头疼。作为个人来说也很想寻找一款跨语言、高速的消息队列“玩一玩”,发现zeromq比较满足这个要求。 ...

DEC_LIU
2013/09/05
4.7K
0
评估了zeromq 和nanomsg -- 两个凡是

本来比较偏好 C 开发的nanomsg 如果zeromq是C开发的, 毫无疑问zeromq 但是 nanomsg 验证不够 根据调查, zeromq胜出 虽然我非常讨厌C++

宏哥
2016/12/31
2.4K
3

没有更多内容

加载失败,请刷新页面

加载更多

Leetcode PHP题解--D118 350. Intersection of Two Arrays II

D118 350. Intersection of Two Arrays II 题目链接 350. Intersection of Two Arrays II 题目分析 返回给定两个数组的交集。 思路 从数量较多的那个数组开始去另一个数组寻找是否元素存在,...

skys215
13分钟前
2
0
从源码上分析Android View保存数据状态

在Android开发旅途中,经常会遇到系统控件无法满足我们的视觉,交互效果,这个时候我们常常需要自己自定义控件来满足我们的需求。在这个开发探索过程中,我们不可避免得遇到View要保存状态信...

shzwork
14分钟前
2
0
请问AD603AQ和AD603AR有什么区别?

  AD603AQ和AD603AR只是在封装上的区别,前者是双列直插式,后者是贴片式,AD603A系列的温度都是在—40摄氏度到+85摄氏度之间,AD603还有一个系列是AD603S,它的温度是在—55摄氏度到+125摄...

仙溪
15分钟前
2
0
Linux /etc/profile 配置文件修改

1. 执行命令: vi /etc/profile 去类似windows 配置环境变量, 2.修改完,立即生效命令: source /etc/profile

kuchawyz
16分钟前
2
0
对于小白来说素描怎么入门?怎么学习?

素描初学者怎样入门?初学者怎样才能画好素描绘画?画好素描绘画有哪些技巧?想必这些问题都是绘画初学者们比较伤脑筋的问题,那么初学者到底怎样才能画好素描绘画呢?今天收集整理了关于素描...

huihuajiaocheng
17分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部