消息订阅程序
#ifndef RABBITMQ_H
#define RABBITMQ_H
#include <iostream>
#include <string>
#include <amqp.h>
#include <amqp_tcp_socket.h>
using namespace std;
class RabbitMQ
{
public:
RabbitMQ();
~RabbitMQ();
///
/// \brief process 获取到要分析显示的信息msg
/// \param msg
/// \return
///
int process(const char *msg);
///
/// \brief consumer 消费者
/// \return
///
int consumer();
///
/// \brief produce_connect 链接生产者
/// \return
///
int produce_connect();
///
/// \brief produce_publish 生产者发布消息msg
/// \param msg
/// \return
///
///
int produce_publish(const char* msg);
///
/// \brief produce_close关闭生产者
/// \return
///
int produce_close();
///
/// \brief ErrorMsg 错误信息
/// \param x
/// \param context
/// \return
///
int ErrorMsg(amqp_rpc_reply_t x, char const *context);
private:
string m_honstname; //虚拟主机ip
int m_port;//端口号
string m_exchange;//交换器名称
string m_routingkey; //绑定路由的key对应消费者
amqp_connection_state_t connection;
int reconnect; //重新链接
};
#endif // RABBITMQ_H
#include "rabbitmq.h"
#include <unistd.h>
RabbitMQ::RabbitMQ()
{
m_honstname = "127.0.0.1";
m_port = 5672;
m_exchange = "ExchangeTest";
m_routingkey = "RoutingkeyTest";
reconnect = 0;
}
RabbitMQ::~RabbitMQ()
{
}
int RabbitMQ::process(const char *msg)
{
cout<<"process msg "<<msg<<endl;
return 0;
}
int RabbitMQ::consumer()
{
int status = 0;
amqp_socket_t *socket = NULL;
amqp_connection_state_t conn;
amqp_rpc_reply_t reply;
int ret = 0;
int quit = 0;
amqp_bytes_t queuename;
while (true) {
//分配和初始化一个新的链接对象
conn = amqp_new_connection();
//创建tcp socket链接
socket = amqp_tcp_socket_new(conn);
if(!socket) {
perror("creating TCP socket");
//销毁链接
amqp_destroy_connection(conn);
sleep(1);
continue;
}
//非阻塞方式打开socket链接
status = amqp_socket_open(socket, m_honstname.c_str(), m_port);
if(status) {
perror("consumer: opening TCP socket");
amqp_destroy_connection(conn);
sleep(1);
continue;
}
//登录Rabbitmq
reply = amqp_login(conn, "/", 0, 131072, 20, AMQP_SASL_METHOD_PLAIN, "guest", "guest");
if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
perror("consumer: failed to login rabbitmq");
//关闭链接
reply = amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
ret = amqp_destroy_connection(conn);
sleep(1);
continue;
}
//打开链接通道
amqp_channel_open(conn, 1);
reply = amqp_get_rpc_reply(conn);
if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
perror("Opening channel");
amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
amqp_destroy_connection(conn);
sleep(1);
continue;
}
amqp_bytes_t queue;
char mac[18] = "b827eb1f1f98";
queue.bytes = mac;
queue.len = 12;
//声明队列
amqp_queue_declare_ok_t *declare = amqp_queue_declare(conn, 1, queue, 0, 0, 0, 1, amqp_empty_table);
reply = amqp_get_rpc_reply(conn);
if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
perror("Declaring queue");
amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
amqp_destroy_connection(conn);
sleep(1);
continue;
}
queuename = amqp_bytes_malloc_dup(declare->queue);
if(queuename.bytes == NULL) {
cout<<"out of memory while copying queue name"<<endl;
amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
amqp_destroy_connection(conn);
sleep(1);
continue;
}
//绑定交换接和队列
amqp_queue_bind(conn, 1, queuename, amqp_cstring_bytes(m_exchange.c_str()), amqp_cstring_bytes(m_routingkey.c_str()), amqp_empty_table);
reply = amqp_get_rpc_reply(conn);
if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
perror("Binding queue");
amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
amqp_destroy_connection(conn);
sleep(1);
continue;
}
//开启一个队列消费者
amqp_basic_consume(conn, 1, queuename, amqp_empty_bytes, 0, 1, 0, amqp_empty_table);
reply = amqp_get_rpc_reply(conn);
if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
perror("Consuming");
amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
amqp_destroy_connection(conn);
sleep(1);
continue;
}
cout << "MQ消费者启动完毕"<<endl;
while (true) {
amqp_envelope_t envelope;
amqp_maybe_release_buffers(conn);
struct timeval timeout = {20, 0};
//接收消息
reply = amqp_consume_message(conn, &envelope, &timeout, 0);
if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
if(reply.library_error != AMQP_STATUS_TIMEOUT) {
perror("message");
amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
amqp_destroy_connection(conn);
break;
}
if(!reconnect)
continue;
reconnect = 0;
perror("message");
amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
amqp_destroy_connection(conn);
break;
}
quit = process((char*)envelope.message.body.bytes);
//销毁消息包
amqp_destroy_envelope(&envelope);
if(quit)
break;
}
if(quit)
break;
}
reply = amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
if(reply.reply_type != AMQP_RESPONSE_NORMAL)
perror("consum: closing channel");
reply = amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
if(reply.reply_type != AMQP_RESPONSE_NORMAL)
perror("closing connection");
ret = amqp_destroy_connection(conn);
if(ret != AMQP_STATUS_OK)
perror("Ending connection");
cout<<"MQ消费者成功退出"<<endl;
return 0;
}
int RabbitMQ::produce_connect()
{
int status = 0;
amqp_socket_t *socket = NULL;
amqp_rpc_reply_t reply;
amqp_bytes_t queuename;
while (true) {
connection = amqp_new_connection();
socket = amqp_tcp_socket_new(connection);
if(!socket) {
perror("produce: creating TCP socket");
reconnect = 1;
amqp_destroy_connection(connection);
sleep(1);
continue;
}
status = amqp_socket_open(socket, m_honstname.c_str(), m_port);
if(status) {
perror("produce: opening TCP socket");
reconnect = 1;
amqp_destroy_connection(connection);
sleep(1);
continue;
}
reply = amqp_login(connection, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, "guest", "guest");
if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
perror("produce: failed to log in rabbitmq");
reconnect = 1;
amqp_connection_close(connection, AMQP_REPLY_SUCCESS);
amqp_destroy_connection(connection);
sleep(1);
continue;
}
amqp_channel_open(connection, 1);
reply = amqp_get_rpc_reply(connection);
if(reply.reply_type != AMQP_RESPONSE_NORMAL){
perror("produce: Opening channel");
reconnect = 1;
amqp_connection_close(connection, AMQP_REPLY_SUCCESS);
amqp_destroy_connection(connection);
continue;
}
// 声明交换机类型
// fanout 广播 direct直接绑定 topic主题模糊匹配
// passive durable exclusive auto_delete 这四个变量要对应消费者那边定义的来决定是0还是1
amqp_exchange_declare(connection, 1, amqp_cstring_bytes(m_exchange.c_str()), amqp_cstring_bytes("topic"), 0, 1, 0, 0, amqp_empty_table);
reply = amqp_get_rpc_reply(connection);
if(0 != ErrorMsg(reply, "Declaring exchange")) {
perror("Declaring exchange");
amqp_channel_close(connection, 1, AMQP_REPLY_SUCCESS);
amqp_connection_close(connection, AMQP_REPLY_SUCCESS);
amqp_destroy_connection(connection);
sleep(1);
continue;
}
amqp_bytes_t queue;
char mac[18] = "b827eb1f1f98";
queue.bytes = mac;
queue.len = sizeof (mac);
//声明队列
//passive durable exclusive auto_delete 这四个变量要对应消费者那边定义的来决定是0还是1
amqp_queue_declare_ok_t *declare = amqp_queue_declare(connection, 1, queue, 0, 1, 0, 0, amqp_empty_table);
reply = amqp_get_rpc_reply(connection);
if(0 != ErrorMsg(reply, "Declaring queue")) {
perror("Declaring queue");
amqp_channel_close(connection, 1, AMQP_REPLY_SUCCESS);
amqp_connection_close(connection, AMQP_REPLY_SUCCESS);
amqp_destroy_connection(connection);
sleep(1);
continue;
}
queuename = amqp_bytes_malloc_dup(declare->queue);
if(queuename.bytes == NULL) {
cout<<"out of memory while copying queue name"<<endl;
amqp_channel_close(connection, 1, AMQP_REPLY_SUCCESS);
amqp_connection_close(connection, AMQP_REPLY_SUCCESS);
amqp_destroy_connection(connection);
sleep(1);
continue;
}
//绑定交换接和队列
amqp_queue_bind(connection, 1, queuename, amqp_cstring_bytes(m_exchange.c_str()), amqp_cstring_bytes(m_routingkey.c_str()), amqp_empty_table);
reply = amqp_get_rpc_reply(connection);
if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
perror("Binding queue");
amqp_channel_close(connection, 1, AMQP_REPLY_SUCCESS);
amqp_connection_close(connection, AMQP_REPLY_SUCCESS);
amqp_destroy_connection(connection);
sleep(1);
continue;
}
break;
}
return 0;
}
int RabbitMQ::produce_publish(const char *msg)
{
int ret = AMQP_STATUS_OK;
amqp_basic_properties_t properties;
properties._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG;
properties.content_type = amqp_cstring_bytes("text/plain");
properties.delivery_mode = 2;
//发布消息
ret = amqp_basic_publish(connection, 1, amqp_cstring_bytes(m_exchange.c_str()), amqp_cstring_bytes(m_routingkey.c_str()), 0, 0, &properties, amqp_cstring_bytes(msg));
if(ret != AMQP_STATUS_OK) {
reconnect = 1;
perror("produce: publish failed");
return -1;
} else {
reconnect = 0;
cout<<"produce publish: "<<msg<<endl;
return 0;
}
return 0;
}
int RabbitMQ::produce_close()
{
amqp_rpc_reply_t reply;
int ret = 0;
reply = amqp_channel_close(connection, 1, AMQP_REPLY_SUCCESS);
if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
perror("produce: Closing channel failed");
ret = -1;
}
reply = amqp_connection_close(connection, AMQP_REPLY_SUCCESS);
if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
perror("produce: Closing connection failed");
ret = -2;
}
ret = amqp_destroy_connection(connection);
if(ret != AMQP_STATUS_OK) {
perror("produce: Ending connection");
return -3;
}
return ret;
}
int RabbitMQ::ErrorMsg(amqp_rpc_reply_t x, char const *context)
{
switch (x.reply_type) {
case AMQP_RESPONSE_NORMAL:
return 0;
case AMQP_RESPONSE_NONE:
fprintf(stderr, "%s: missing RPC reply type!\n", context);
break;
case AMQP_RESPONSE_LIBRARY_EXCEPTION:
fprintf(stderr, "%s: %s\n", context, amqp_error_string2(x.library_error));
break;
case AMQP_RESPONSE_SERVER_EXCEPTION:
switch (x.reply.id) {
case AMQP_CONNECTION_CLOSE_METHOD: {
amqp_connection_close_t *m = (amqp_connection_close_t *)x.reply.decoded;
fprintf(stderr, "%s: server connection error %uh, message: %.*s\n",
context, m->reply_code, (int)m->reply_text.len,
(char *)m->reply_text.bytes);
break;
}
case AMQP_CHANNEL_CLOSE_METHOD: {
amqp_channel_close_t *m = (amqp_channel_close_t *)x.reply.decoded;
fprintf(stderr, "%s: server channel error %uh, message: %.*s\n",
context, m->reply_code, (int)m->reply_text.len,
(char *)m->reply_text.bytes);
break;
}
default:
fprintf(stderr, "%s: unknown server error, method id 0x%08X\n",
context, x.reply.id);
break;
}
break;
}
return -1;
}
#include <iostream>
#include <pthread.h>
#include "rabbitmq.h"
#include <unistd.h>
#include <string.h>
using namespace std;
RabbitMQ rabbitmq;
void consume()
{
rabbitmq.consumer();
}
void produce()
{
while (true) {
rabbitmq.produce_connect();
rabbitmq.produce_publish("I am hello world");
rabbitmq.produce_close();
sleep(1);
}
}
int main(int argc, char** argv)
{
cout << "Hello World!" << endl;
if(strcmp(argv[1], "first") == 0) {
cout<<"this is consume"<<endl;
consume();
} else if(strcmp(argv[1], "second") == 0) {
cout<<"this is produce"<<endl;
produce();
}
return 0;
}