zeromqc源码(zeromq python)
本文目录一览:
zeromq解决了什么问题
很早就听说了zeromq 这个项目,当时不太在意. 后来同事kasicass 对这个项目做了研究和分享 ,开始重视起这个项目来. 1) libevent封装了对网络I/O,信号,定时器等的处理,可以基于它之上做网络层的开发. 2) ACE封装了不同平台下的系统调用,也提供好几种网络编程的模型. 然而,zeromq不是libevent,也不是ACE,因为它的主要特性是:面向消息进行通信.所以,它提供的是比libevent,ACE处在网络通信中更高一层的组件.使用它,程序员不再需要上面提到的libevent,ACE之类的库需要关心的东西,程序员如果要使用zeromq,只需要做如下的事情: 1) 告知所使用的patten,比如request-reply,pub-sub,push-pull等(下面会详细解释这个pattern). 2) 告知是用于机器之间,还是进程之间,线程之间的通信. 然后,将所需要发送的数据封装到zeromq自带的msg结构体中发送出去,使用者自己关心如何序列化/反序列化这些数据,然后如何处理这些数据就是使用者的事情了.这样看上来,使用者要关注的事情”高”了一层,大部分的精力都可以放在业务逻辑之上了.简而言之,它让使用者的精力放在了通信模式和业务逻辑上,而不是更下面一层的网络层上.下面解释一下zeromq常用的几种网络pattern: 1) request-reply 就是一般的C/S架构中,client与server之间一问一答的通信模式,比如最经典的echo服务.需要注意的是,client发送一个request,server必须有一个回应. server端作为publish端,而任何连接到服务端的client都会成为subscribe端.也就是说,server端会把当前的所有需要publish出去的消息全部发送到当前连接上去的client上.3) push-pull server端作为push端,而client端作为pull端.如果有多个client端同时连接到这个server,则服务器会在内部做一个负载均衡,采用平均分配的算法,将所有的消息均衡发布到client端上.看上去,很稀松平常?接下来亮点真的来了.考虑如下一种场景.一个server端做为一组服务器集群最上层的一个proxy,起到负载均衡的作用,将请求按照它下面对应服务器集群依次派发到不同的 client端进行处理.某个时刻可能处理的机器只有2台,而随着负载越来越大,可能需要3台机器了,这个时候如果使用zeromq的push-pull 搭建的proxy端,则可以不用对之前搭建的server,client端进行停机,只需要新启动一个client连接上去,proxy层就会自动根据当前的机器分配平均派发任务了.cool.实际上,这些模式并不是什么新东西,只不过zeromq为使用者做了一个封装,而不是像libevent,ACE等还局限在网络层部分的封装,它关注的是通信层,通信模式等.个人感觉,zeromq部分解决 了erlang所要解决的问题:在多台机器中通信,派发任务等,是分布式通信的利器,但是局限于语言的限制,它没有办法做的跟erlang一样的完善(erlang已经可以算的上一个简易微型的OS了),但是许多的时候,似乎只使用这一部分功能也就足够了.zeromq的代码量,截至到我目前阅读的2.0.10-stable版本,也只有不到2W行代码.提供出去的API也极为简单,但是内部的实现比较”绕”,zeromq是我阅读过的项目中少数的非常需要依赖调试工具跟进代码才能看懂代码流程的项目,同时代码中类的继承层次也比较多,阅读起来并不像它提供的API那样简单直白.后续会对其中的一些难点做一些分析.
为啥linux使用zeromq出现未定义zmq
Windows下VS2008使用ZeroMQ说明一、下载ZeroMQ
二、编译ZeroMQ库文件
解压zeromq-4.0.3.zip文件zeromqc源码,进入builds\msvc目录zeromqc源码,用VS打开*.sln工程文件,编译生成解决方案。编译完成后,会在lib目录下生成dll和lib文件
三、编写简单的测试工程
用VS新建2个项目,一个是server端,一个是client端
将ZeroMQ源码项目的include目录下的两个文件“zmq.h”,“zmq_utils.h”拷贝至自己新建的工程
将ZeroMQ源码项目的lib目录下的两个文件“libzmq.dll”,“libzmq.lib”拷贝至自己新建的工程
将文件“zmq.h”,“zmq_utils.h”和“libzmq.lib”添加进自己新建的项目。
client端代码zeromqc源码:
#include stdio.h
#include iostream
#include string.h
#include "zeroMQ/zmq.h"
#include "zeroMQ/zmq_utils.h"
int main(int argc,char** argv)
为什么我希望用C而不是C++来实现ZeroMQ
在我的整个职业生涯里我都在使用C++,而且现在C++依然是我做大多数项目时的首选编程语言。自然的,当我从2007年开始做ZeroMQ(ZeroMQ项目主页)时,我选择用C++来实现。主要的原因有以下几点:1. 包含数据结构和算法的库(STL)已经成为这个语言的一部分了。如果用C,我将要么依赖第三方库要么不得不自己手动写一些自1970年来就早已存在的基础算法。2. C++语言本身在编码风格的一致性上起到了一些强制作用。比如,有了隐式的this指针参数,这就不允许通过各种不同的方式将指向对象的指针做转换,而那种做法在C项目中常常见到(通过各种类型转换)。同样的还有可以显式的将成员变量定义为私有的,以及许多其他的语言特性。3. 这个观点基本上是前一个的子集,但值得我在这里显式的指出:用C语言实现虚函数机制比较复杂,而且对于每个类来说会有些许的不同,这使得对代码的理解和维护都会成为痛苦之源。4. 最后一点是:人人都喜欢析构函数,它能在变量离开其作用域时自动得到调用。如今,5年过去了,我想公开承认:用C++作为ZeroMQ的开发语言是一个糟糕的选择,后面我将一一解释为什么我会这么认为。首先,很重要的一点是ZeroMQ是需要长期连续不停运行的一个网络库。它应该永远不会出错,而且永远不能出现未定义的行为。因此,错误处理对于ZeroMQ来说至关重要,错误处理必须是非常明确的而且对错误应该是零容忍的。C++的异常处理机制却无法满足这个要求。C++的异常机制对于确保程序不会失败是非常有效的——只要将主函数包装在try/catch块中,然后你就可以在一个单独的位置处理所有的错误。然而,当你的目标是确保没有未定义行为发生时,噩梦就产生了。C++中引发异常和处理异常是松耦合的,这使得在 C++中避免错误是十分容易的,但却使得保证程序永远不会出现未定义行为变得基本不可能。在C语言中,引发错误和处理错误的部分是紧耦合的,它们在源代码中处于同一个位置。这使得我们在错误发生时能很容易理解到底发生了什么:int rc = fx (); if (rc != 0) handle_error();在C++中,你只是抛出一个异常,到底发生了什么并不能马上得知。int rc = fx(); if (rc != 0) throw std::exception();这里的问题就在于你对于谁处理这个异常,以及在哪里处理这个异常是不得而知的。如果你把异常处理代码也放在同一个函数中,这么做或多或少还有些明智,尽管这么做会牺牲一点可读性。try { … int rc = fx(); if (rc != 0) throw std::exception(“Error!”); … catch (std::exception e) { handle_exception(); }但是,考虑一下,如果同一个函数中抛出了两个异常时会发生什么?class exception1 {}; class exception2 {}; try { … if (condition1) throw my_exception1(); … if (condition2) throw my_exception2(); … } catch (my_exception1 e) { handle_exception1(); } catch (my_exception2 e) { handle_exception2(); }对比一下相同的C代码:… if (condition1) handle_exception1(); … if (condition2) handle_exception2(); …C代码的可读性明显高的多,而且还有一个附加的优势——编译器会为此产生更高效的代码。这还没完呢。再考虑一下这种情况:异常并不是由所抛出异常的函数来处理。在这种情况下,异常处理可能发生在任何地方,这取决于这个函数是在哪调用的。虽然乍一看我们可以在不同的上下文中处理不同的异常,这似乎很有用,但很快就会变成一场噩梦。当你在解决bug的时候,你会发现几乎同样的错误处理代码在许多地方都出现过。在代码中增加一个新的函数调用可能会引入新的麻烦,不同类型的异常都会涌到调用函数这里,而调用函数本身并没有适当进行的处理,这意味着什么?新的bug。如果你依然坚持要杜绝“未定义的行为”,你不得不引入新的异常类型来区分不同的错误模式。然而,增加一个新的异常类型意味着它会涌现在各个不同的地方,那么就需要在所有这些地方都增加一些处理代码,否则你又会出现“未定义的行为”。到这里你可能会尖叫:这特么算什么异常规范哪!好吧,问题就在于异常规范只是以一种更加系统化的方式,以按照指数规模增长的异常处理代码来处理问题的工具,它并没有解决问题本身。甚至可以说现在情况更加糟糕了,因为你不得不去写新的异常类型,新的异常处理代码,以及新的异常规范。通过上面我描述的问题,我决定使用去掉异常处理机制的C++。这正是ZeroMQ以及Crossroads I/O今天的样子。但是,很不幸,问题到这并没有结束…考虑一下当一个对象初始化失败的情况。构造函数没有返回值,因此出错时只能通过抛出异常来通知出现了错误。可是我已经决定不使用异常了,那么我不得不这样做:class foo { public: foo(); int init(); … };当你创建这个类的实例时,构造函数被调用(不允许失败),然后你显式的去调用init来初始化(init可能会失败)对象。相比于C语言中的做法,这就显得过于复杂了。struct foo { … }; int foo_init(struct foo *self);但是以上的例子中,C++版本真正邪恶的地方在于:如果有程序员往构造函数中加入了一些真正的代码,而不是将构造函数留空时会发生什么?如果有人真的这么做了,那么就会出现一个新的特殊的对象状态——“半初始化状态”。这种状态是指对象已经完成了构造(构造函数调用完成,且没有失败),但init函数还没有被调用。我们的对象需要修改(特别是析构函数),这里应该以一种方式妥善的处理这种新的状态,这就意味着又要为每一个方法增加新的条件。看到这里你可能会说:这就是你人为的限制使用异常处理所带来的后果啊!如果在构造函数中抛出异常,C++运行时库会负责清理适当的对象,那这里根本就没有什么“半初始化状态”了!很好,你说的很对,但这根本无关紧要。如果你使用异常,你就不得不处理所有那些与异常相关的复杂情况(我前面已经描述过了)。而这对于一个面对错误时需要非常健壮的基础组件来说并不是一个合理的选择。此外,就算初始化不是问题,那析构的时候绝对会有问题。