网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
redisContext *_subcribe_context;
// 回调操作,收到订阅的消息,给service层上报
function<void(int, string)> _notify_message_handler;
};
#endif
这一套,可以在做轻量级集群服务器间通信用,封装好了的。
#include “redis.hpp”
#include
using namespace std;
Redis::Redis():_publish_context(nullptr), _subcribe_context(nullptr){}
Redis::~Redis(){
if (_publish_context != nullptr){
redisFree(_publish_context);
}
if (_subcribe_context != nullptr){
redisFree(_subcribe_context);
}
}
bool Redis::connect(){
// 负责publish发布消息的上下文连接
_publish_context = redisConnect(“127.0.0.1”, 6379);
if (nullptr == _publish_context){
cerr << “connect redis failed!” << endl;
return false;
}
// 负责subscribe订阅消息的上下文连接
_subcribe_context = redisConnect(“127.0.0.1”, 6379);
if (nullptr == _subcribe_context){
cerr << “connect redis failed!” << endl;
return false;
}
// 在单独的线程中,监听通道上的事件,有消息给业务层进行上报
thread t(& {
observer_channel_message();
});
t.detach();
cout << “connect redis-server success!” << endl;
return true;
}
// 向redis指定的通道channel发布消息
bool Redis::publish(int channel, string message){
redisReply *reply = (redisReply *)redisCommand(_publish_context, “PUBLISH %d %s”, channel, message.c_str());
if (nullptr == reply){
cerr << “publish command failed!” << endl;
return false;
}
freeReplyObject(reply);
return true;
}
// 向redis指定的通道subscribe订阅消息
bool Redis::subscribe(int channel){
// SUBSCRIBE命令本身会造成线程阻塞等待通道里面发生消息,这里只做订阅通道,不接收通道消息
// 通道消息的接收专门在observer_channel_message函数中的独立线程中进行
// 只负责发送命令,不阻塞接收redis server响应消息,否则和notifyMsg线程抢占响应资源
if (REDIS_ERR == redisAppendCommand(this->_subcribe_context, “SUBSCRIBE %d”, channel)){
cerr << “subscribe command failed!” << endl;
return false;
}
// redisBufferWrite可以循环发送缓冲区,直到缓冲区数据发送完毕(done被置为1)
int done = 0;
while (!done){
if (REDIS_ERR == redisBufferWrite(this->_subcribe_context, &done)){
cerr << “subscribe command failed!” << endl;
return false;
}
}
// redisGetReply
return true;
}
// 向redis指定的通道unsubscribe取消订阅消息
bool Redis::unsubscribe(int channel){
if (REDIS_ERR == redisAppendCommand(this->_subcribe_context, “UNSUBSCRIBE %d”, channel)){
cerr << “unsubscribe command failed!” << endl;
return false;
}
// redisBufferWrite可以循环发送缓冲区,直到缓冲区数据发送完毕(done被置为1)
int done = 0;
while (!done){
if (REDIS_ERR == redisBufferWrite(this->_subcribe_context, &done)){
cerr << “unsubscribe command failed!” << endl;
return false;
}
}
return true;
}
// 在独立线程中接收订阅通道中的消息
void Redis::observer_channel_message(){
redisReply *reply = nullptr;
while (REDIS_OK == redisGetReply(this->_subcribe_context, (void **)&reply)){
// 订阅收到的消息是一个带三元素的数组
if (reply != nullptr && reply->element[2] != nullptr && reply->element[2]->str != nullptr)
{
// 给业务层上报通道上发生的消息
_notify_message_handler(atoi(reply->element[1]->str) , reply->element[2]->str);
}
freeReplyObject(reply);
}
cerr << “>>>>>>>>>>>>> observer_channel_message quit <<<<<<<<<<<<<” << endl;
}
void Redis::init_notify_handler(function<void(int,string)> fn){
this->_notify_message_handler = fn;
}
头文件里面自行修改吧,这里放出源文件的修改范围。
构造函数中连接上redis:
// 连接redis服务器
if (_redis.connect()){
// 设置上报消息的回调
_redis.init_notify_handler(std::bind(&ChatService::handleRedisSubscribeMessage, this, _1, _2));
}
登录成功后,向redis消息队列进行订阅:
// id用户登录成功后,向redis订阅channel(id)
_redis.subscribe(id);
用户注销之后,取消订阅:
// 用户注销,相当于就是下线,在redis中取消订阅通道
_redis.unsubscribe(userid);
(客户端里以外掉线也给它来上这么一下)
单聊:
//一对一聊天
void ChatService::onechat(const TcpConnectionPtr &conn,json &js,Timestamp time){
// cout<<js<<endl;
int toid = js[“toid”].get(); //这里bug
// bool userstate = false;
//开辟锁的作用域
{
lock_guard lock(_connMutex);
auto it = _userConnMap.find(toid);
if(it != _userConnMap.end()){
//用户在线,转发消息
it->second->send(js.dump());
return;
}
}
// 查询toid是否在线
User user = _usermodel.query(toid);
if (user.getstate() == “online”){
_redis.publish(toid, js.dump());
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
el.query(toid);
if (user.getstate() == “online”){
_redis.publish(toid, js.dump());
[外链图片转存中…(img-fb1ndI3o-1715569310210)]
[外链图片转存中…(img-DbxVWD6R-1715569310211)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!