I want to use RabbitMq in my c++ program. I desided to use AMQP-CPP for this.
When I used class MyConnectionHandler : public AMQP::ConnectionHandler
from README file my messages weren't sent. Here is that class
#include <amqpcpp.h>
/** You'll need to extend the ConnectionHandler class and make your own, like this*/
class MyConnectionHandler : public AMQP::ConnectionHandler
{
/**
* Method that is called by the AMQP library every time it has data
* available that should be sent to RabbitMQ.
* @param connection pointer to the main connection object
* @param data memory buffer with the data that should be sent to RabbitMQ
* @param size size of the buffer
*/
virtual void onData(AMQP::Connection *connection, const char *data, size_t size)
{
// @todo
// Add your own implementation, for example by doing a call to the
// send() system call. But be aware that the send() call may not
// send all data at once, so you also need to take care of buffering
// the bytes that could not immediately be sent, and try to send
// them again when the socket becomes writable again
}
/**
* Method that is called by the AMQP library when the login attempt
* succeeded. After this method has been called, the connection is ready
* to use.
* @param connection The connection that can now be used
*/
virtual void onReady(AMQP::Connection *connection)
{
// @todo
// add your own implementation, for example by creating a channel
// instance, and start publishing or consuming
}
/**
* Method that is called by the AMQP library when a fatal error occurs
* on the connection, for example because data received from RabbitMQ
* could not be recognized.
* @param connection The connection on which the error occurred
* @param message A human readable error message
*/
virtual void onError(AMQP::Connection *connection, const char *message)
{
// @todo
// add your own implementation, for example by reporting the error
// to the user of your program, log the error, and destruct the
// connection object because it is no longer in a usable state
}
/**
* Method that is called when the connection was closed. This is the
* counter part of a call to Connection::close() and it confirms that the
* AMQP connection was correctly closed.
*
* @param connection The connection that was closed and that is now unusable
*/
virtual void onClosed(AMQP::Connection *connection)
{
// @todo
// add your own implementation, for example by closing down the
// underlying TCP connection too
}
};
In each method I wrote only std::cout
with name of methods.
Then I found class MyHandler : public AMQP::LibEvHandler
in examples that used libev
Example with libev and my message was sent.
But I didn't understand how to put my own text of message in that publisher into loop. I found an example look at void Client::publish(std::string message) method I think this is wrong becouse every time connection and channel are created and queue and exchange are declared. I think my code will send messages every 1-5 seconds. And this method is bad.
I made my methods
class MessageWatcher {
public:
ev_idle evIdle;
std::string message;
std::string exchanger;
std::string routingKey;
AMQP::TcpChannel * channel;
MessageWatcher(const std::string &exchanger, const std::string &routingKey)
: exchanger(exchanger), routingKey(routingKey) {}
};
static void publishEvent (EV_P_ ev_idle * watcher, int revents) {
auto * self = (class MessageWatcher *)watcher;
std::cout << self->message << '\n';
self->channel->publish(self->exchanger, self->routingKey, self->message);
ev_idle_stop (EV_A_ watcher);
ev_break (EV_A_ EVBREAK_ALL);
}
void rabbitWorker(MessageWatcher & messageWatcher, struct ev_loop * loop) {
static RabbitMqConnectionHandler handler(loop);
static AMQP::TcpConnection connection(&handler,
AMQP::Address("amqp://guest:guest@localhost/my-vhost"));
static AMQP::TcpChannel channel(&connection);
// channel.publish("betweenIslands", "migrationToNewIsland", "my first message");
messageWatcher.channel = &channel;
ev_idle_init (&messageWatcher.evIdle, publishEvent);
ev_idle_start (loop, &messageWatcher.evIdle);
ev_run(loop, 0);
}
int main() {
struct ev_loop * loop{EV_DEFAULT};
MessageWatcher messageWatcher{"exchangeName", "routingKeyName"};
messageWatcher.message = "start message";
rabbitWorker(messageWatcher, loop);
short counter1{10};
while (--counter1) {
sleep(3);
std::cout << "3 seconds is over" << '\n';
messageWatcher.message = "message after 3 seconds number is " +
std::to_string(counter1);
ev_invoke(loop, &messageWatcher.evIdle, 0);
}
Queue and exchange is declared already. But my code writes self->message only and don't publishes it in queue. When I uncomment channel.publish("betweenIslands", "migrationToNewIsland", "my first message");
and comment 3 further strings than "my first message" is sent. But how to put my own message
instead "my first message"
in this case?