Skip to content

Commit eec7793

Browse files
committed
Initial commit
0 parents  commit eec7793

11 files changed

+604
-0
lines changed

App.cc

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include "App.h"
2+
3+
#include <QTimer>
4+
#include <QStringList>
5+
#include <QCoreApplication>
6+
#include <QtDebug>
7+
#include <QDateTime>
8+
9+
#include "ZmqSocket.h"
10+
#include "ZmqMessage.h"
11+
12+
App::App()
13+
{
14+
QTimer::singleShot(0, this, SLOT(start()));
15+
}
16+
17+
void App::start()
18+
{
19+
QStringList args = QCoreApplication::arguments();
20+
if(args.size() < 3) {
21+
qWarning() << "Usage: " << args.front() << " client|server <key>";
22+
QCoreApplication::exit();
23+
return;
24+
}
25+
26+
key = args.at(2).toLocal8Bit();
27+
28+
QTimer *ndyt = new QTimer(this);
29+
connect(ndyt, SIGNAL(timeout()), this, SLOT(ndy()));
30+
ndyt->setInterval(5000);
31+
ndyt->start();
32+
33+
if(args.at(1) == "client") {
34+
sock = new ZmqSocket(ZMQ_SUB, this);
35+
connect(sock, SIGNAL(readyRead()), this, SLOT(heard()));
36+
sock->subscribe(key);
37+
sock->connectTo("tcp://127.0.0.1:3782");
38+
}
39+
40+
if(args.at(1) == "server") {
41+
sock = new ZmqSocket(ZMQ_PUB, this);
42+
sock->bind("tcp://127.0.0.1:3782");
43+
QTimer *t = new QTimer(this);
44+
connect(t, SIGNAL(timeout()), this, SLOT(squawk()));
45+
t->setInterval(1000);
46+
t->start();
47+
}
48+
}
49+
50+
void App::squawk()
51+
{
52+
QString s = QDateTime::currentDateTime().toString();
53+
qDebug() << "Squawking " << s;
54+
sock->send(key + s.toLocal8Bit());
55+
}
56+
57+
void App::heard()
58+
{
59+
QList<QByteArray> r = sock->recv();
60+
for(QList<QByteArray>::const_iterator i=r.constBegin(); i!=r.constEnd(); ++i) {
61+
qDebug() << "Received " << *i;
62+
}
63+
}
64+
65+
void App::ndy()
66+
{
67+
qDebug() << "Not dead yet";
68+
}

App.h

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#ifndef APP_H
2+
#define APP_H
3+
4+
#include <QObject>
5+
6+
class ZmqSocket;
7+
8+
class App : public QObject
9+
{
10+
Q_OBJECT
11+
public:
12+
App();
13+
protected slots:
14+
void start();
15+
void squawk();
16+
void heard();
17+
void ndy();
18+
private:
19+
ZmqSocket *sock;
20+
QByteArray key;
21+
};
22+
23+
#endif // APP_H

README.markdown

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
Zeromqt - a [Qt][] binding for [ZeroMQ][]
2+
=========================================
3+
4+
Zeromqt integrates ZeroMQ (version 2.1.0 and later) into the Qt event loop,
5+
mapping ZeroMQ message events onto Qt signals.
6+
7+
It also provides an API that is more "Qt-like" than the native ZeroMQ C or C++
8+
APIs, allowing messages to be handled as QByteArrays and providing classes
9+
that are similar in style to QAbstractSocket.
10+
11+
Status
12+
------
13+
14+
Pre-alpha.
15+
16+
There are no known bugs, but nor has there been any testing beyond
17+
the included sample app. It's being used as part of a large commercial
18+
application, though, so it'll be getting some testing and attention.
19+
20+
Usage
21+
-----
22+
23+
To use Zeromqt in a Qt project, add this to the projects .pro file
24+
25+
HEADERS += ZmqException.h ZmqMessage.h ZmqSocket.h ZmqContext.h
26+
SOURCES += ZmqSocket.cc ZmqMessage.cc
27+
LIBS += -lzmq
28+
29+
and copy the six Zmq* files into the project.
30+
31+
Exceptions
32+
----------
33+
34+
Zeromqt uses C++ exceptions by default. You'll need to catch ZmqException
35+
objects in the normal way (which on Qt probably involves inheriting from
36+
QCoreAppliction and reimplementing notify()).
37+
38+
There is untested support in the code for replacing exceptions with Qt-style
39+
errorString() error handling instead - look for USE_EXCEPTIONS
40+
41+
Sample
42+
------
43+
44+
There's a single pub-sub sample included. Build it with qmake; make. Run the
45+
server with "./pubsubsample server foo" and the client with
46+
"./pubsubsample client foo".
47+
48+
More Information
49+
----------------
50+
51+
[Word to the Wise Labs](http://labs.wordtothewise.com/zeromqt/)
52+
53+
[qt]: http://qt.nokia.com/ "Qt"
54+
[zeromq]: http://zeromq.com/ "ZeroMQ"

ZmqContext.cc

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include "ZmqContext.h"
2+
3+
#include <zmq.h>
4+
#include <stdio.h>
5+
6+
#include <QtGlobal>
7+
8+
ZmqContext *ZmqContext::self_ = 0;
9+
10+
ZmqContext::ZmqContext(int iothreads, int defaultLinger) : linger_(defaultLinger)
11+
{
12+
Q_ASSERT(!self_);
13+
context_ = zmq_init(iothreads);
14+
if(!context_) {
15+
if(errno == EINVAL) {
16+
qFatal("Invalid number of iothreads (%d) in ZmqContext", iothreads);
17+
} else {
18+
qFatal("Error in ZMQContext: %d %s", errno, zmq_strerror(errno));
19+
}
20+
}
21+
}
22+
23+
ZmqContext::~ZmqContext()
24+
{
25+
zmq_term(context_);
26+
}
27+
28+
int ZmqContext::majorVersion()
29+
{
30+
int major, minor, patch;
31+
zmq_version(&major, &minor, &patch);
32+
return major;
33+
}
34+
35+
int ZmqContext::minorVersion()
36+
{
37+
int major, minor, patch;
38+
zmq_version(&major, &minor, &patch);
39+
return minor;
40+
}
41+
42+
int ZmqContext::patchVersion()
43+
{
44+
int major, minor, patch;
45+
zmq_version(&major, &minor, &patch);
46+
return patch;
47+
}
48+
49+
QString ZmqContext::version()
50+
{
51+
int major, minor, patch;
52+
zmq_version(&major, &minor, &patch);
53+
return QString("%1.%2.%3").arg(major).arg(minor).arg(patch);
54+
}

ZmqContext.h

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#ifndef ZMQCONTEXT_H
2+
#define ZMQCONTEXT_H
3+
4+
#include <QString>
5+
6+
class ZmqContext
7+
{
8+
friend class ZmqSocket;
9+
public:
10+
ZmqContext(int iothreads, int defaultLinger);
11+
~ZmqContext();
12+
static ZmqContext *instance(int iothreads=4, int defaultLinger = 0) {
13+
return self_ ? self_ : new ZmqContext(iothreads, defaultLinger);
14+
}
15+
16+
static int majorVersion();
17+
static int minorVersion();
18+
static int patchVersion();
19+
static QString version();
20+
21+
int linger() const { return linger_; }
22+
void setLinger(int msec) { linger_ = msec; }
23+
24+
private:
25+
static ZmqContext *self_;
26+
void *context_;
27+
int linger_;
28+
29+
};
30+
31+
#endif // ZMQCONTEXT_H

ZmqException.h

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef ZMQEXCEPTION_H
2+
#define ZMQEXCEPTION_H
3+
#include <zmq.h>
4+
#include <stdexcept>
5+
6+
class ZmqException : public std::exception
7+
{
8+
public:
9+
ZmqException() : errno_ (zmq_errno()) {}
10+
virtual const char *what () const throw () {
11+
return zmq_strerror (errno_);
12+
}
13+
int error() const { return errno_; }
14+
private:
15+
int errno_;
16+
};
17+
18+
#endif // ZMQEXCEPTION_H

ZmqMessage.h

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#ifndef ZMQMESSAGE_H
2+
#define ZMQMESSAGE_H
3+
4+
#include <zmq.h>
5+
6+
#ifndef ZMQ_VERSION
7+
#error ZMQ_VERSION not defined - zmq.h is too old - version 2.1.0 is required
8+
#endif
9+
10+
#if ZMQ_VERSION < 20100
11+
#error zmq.h is too old - version 2.1.0 is required
12+
#endif
13+
14+
#include <QString>
15+
#include <QByteArray>
16+
#include <string.h>
17+
#include <assert.h>
18+
19+
#define USE_EXCEPTIONS 1
20+
21+
#ifdef USE_EXCEPTIONS
22+
#include "ZmqException.h"
23+
#define THROW() throw ZmqException()
24+
#else
25+
#define THROW() do { error_ = ZMQERRNO; \
26+
errorString_ = QString::fromAscii(zmq_strerror(error_)); return; }
27+
#endif
28+
29+
class ZmqMessage : private zmq_msg_t
30+
{
31+
friend class ZmqSocket;
32+
public:
33+
ZmqMessage() {
34+
if(0 != zmq_msg_init(this)) THROW();
35+
}
36+
37+
ZmqMessage(size_t size_){
38+
if(0 != zmq_msg_init_size(this, size_)) THROW();
39+
}
40+
41+
ZmqMessage(void *data_, size_t size_, zmq_free_fn *ffn=0, void *hint=0) {
42+
if(0 != zmq_msg_init_data(this, data_, size_, ffn, hint)) THROW();
43+
}
44+
45+
ZmqMessage(const QByteArray& b) {
46+
if(0 != zmq_msg_init_size(this, b.size())) THROW();
47+
memcpy(data(), b.constData(), b.size());
48+
}
49+
50+
~ZmqMessage() {
51+
int rc = zmq_msg_close(this);
52+
assert(rc == 0);
53+
}
54+
void copy(ZmqMessage *msg) {
55+
if(0 != zmq_msg_copy(this, (zmq_msg_t*)msg)) THROW();
56+
}
57+
void move(ZmqMessage *msg) {
58+
if(0 != zmq_msg_move(this, (zmq_msg_t*)msg)) THROW();
59+
}
60+
void clone(ZmqMessage *msg) {
61+
rebuild(msg->size());
62+
memcpy(data(), msg->data(), size());
63+
}
64+
65+
void clear() { rebuild(); }
66+
67+
void rebuild() {
68+
if(0 != zmq_msg_close(this)) THROW();
69+
if(0 != zmq_msg_init(this)) THROW();
70+
}
71+
void rebuild(size_t size_) {
72+
if(0 != zmq_msg_close(this)) THROW();
73+
if(0 != zmq_msg_init_size(this, size_)) THROW();
74+
}
75+
void rebuild(void *data_, size_t size_, zmq_free_fn *ffn=0, void *hint=0) {
76+
if(0 != zmq_msg_close(this)) THROW();
77+
if(0 != zmq_msg_init_data(this, data_, size_, ffn, hint)) THROW();
78+
}
79+
80+
void rebuild(const QByteArray& b) {
81+
if(0 != zmq_msg_close(this)) THROW();
82+
if(0 != zmq_msg_init_size(this, b.size())) THROW();
83+
84+
memcpy(data(), b.constData(), b.size());
85+
}
86+
87+
size_t size() { return zmq_msg_size(this); }
88+
void *data() { return zmq_msg_data(this); }
89+
90+
QByteArray toByteArray() {
91+
return QByteArray((const char *)data(), size());
92+
}
93+
94+
private:
95+
int error_;
96+
QString errorString_;
97+
};
98+
99+
#endif // ZMQMESSAGE_H

0 commit comments

Comments
 (0)