用redis的订阅/发布机制来做1)进程间通信、2)操作hiredis库、3)异步处理hiredis订阅

  • Post author:
  • Post category:其他




一、往1这个通道发布一条信息abc,这里是开启通道

在这里插入图片描述



二、订阅1这个通道的信息(这里别的窗口再输入了一次redis-cli publish 1 abc)

在这里插入图片描述

总的命令查看

在这里插入图片描述

两个人订阅

在这里插入图片描述



三、一些细节



1)一个订阅者可以订阅多个频道(这里订阅订阅了2和3通道)

发布命令:publish 频道名 内容

在这里插入图片描述



2)订阅者(收消息):会一直阻塞等待新消息

订阅命令:subscribe 频道名



3)发布消息会发给所有订阅者



四、hiredis库实现发布订阅



1)初步的代码

#include <cstdip>
#include <hiredis/hiredis.h>
int main()
{
	auto pc = redisConnect("127.0.0.1",6379);
	if(NULL!=pc)
	{	
		//会返回一个指针,要把这个结果指针释放掉
		freeReplyObject(redisCommand(pc,"publish 1 abc"));
		redisFree(pc);
	}
}

在这里插入图片描述

运行后如图所示,订阅者已经收到通道1的消息abc

在这里插入图片描述



2)打印订阅的信息

#include <cstdip>
#include <hiredis/hiredis.h>
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
	auto pc = redisConnect("127.0.0.1",6379);
	if(NULL!=pc)
	{	
		redisReply* reply = (redisReply*)redisCommand(pc,"subscribe 1");//订阅频道1
		if(redis->type==REDIS_REPLY_ARRAY)
		{
			std::cout<<"reply's count:"<<reply->elements<<std::endl;//回复了三个返回值
			puts(reply->element[0]->str);//打印subscribe
			puts(reply->element[1]->str);//打印订阅了哪个频道
			std::cout<<reply->element[2]->integer<<std::endl;//打印订阅的频道数量
		}
		redisFree(pc);
	}
	system("pause");
}


返回值


在这里插入图片描述

  • 关于redisGetReply函数的补充说明

在这里插入图片描述


补充注意点



值得注意的是,调用redisAppendCommand()函数的次数需要与调用redisGetReply()的次数要一致,否则会出现获取的 Redis 处理结果跟预期不一致的情况。

// 测试 redisGetReply 与 redisAppendCommand 调用次数不一致的情况
redisAppendCommand(conn, "get t");
// 本来想取得 set a ddd 的返回,却获取了 get t 的返回
reply = redisCommand(conn, "set a ddd");
printf("set a res: %s\n", reply->str);

输出的结果将会是get t命令的返回,而不是set a ddd命令的返回。



3)开启订阅,然后打印收到的发布的信息

  • 代码

    在这里插入图片描述
  • 发布数据

    在这里插入图片描述
  • 打印数据信息

    在这里插入图片描述



五、异步处理hiredis订阅



1)下面的代码是不对的,得和libevent结合在一起

#include <cstdip>
#include <hiredis/hiredis.h>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <hiredis/async.h>
#include <hiredis/adapters/libevent.h>
using namespace std;

void my_callback(redisAsyncContext* c,void* preply,void* privdata)
{
	redisReply* reply = (redisReply*)preply;
	if("message"==string(reply->element[0]->str))
	{
		std::cout<<"message from channel:"<<string(reply->element[1]->str)<<std::endl;
		std::cout<<"message content is:"<<string(reply->element[2]->str)<<std::endl;
	}
}

void redis_async()
{
	//创建异步连接
	auto pc = redisAsyncConnect("127.0.0.1",6379);
	//异步发送消息(指定回复处理函数)
	redisAsyncCommand(pc,my_callback,NULL,"subscribe 1")
} 

int main()
{
	redis_async();
	getchar();
	return 0;
}



2)举例代码-》官方redis结合libevent图片

在这里插入图片描述

在这里插入图片描述

  • 先发布消息

    在这里插入图片描述