2024年C++搭建集群聊天室(十八):nginx ,Flutter全方位深入探索

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

redisContext *_subcribe_context;

// 回调操作,收到订阅的消息,给service层上报

function<void(int, string)> _notify_message_handler;

};

#endif


redis.cpp


这一套,可以在做轻量级集群服务器间通信用,封装好了的。

#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;

}


chatservice修改


头文件里面自行修改吧,这里放出源文件的修改范围。

构造函数中连接上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());

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

el.query(toid);

if (user.getstate() == “online”){

_redis.publish(toid, js.dump());

[外链图片转存中…(img-fb1ndI3o-1715569310210)]
[外链图片转存中…(img-DbxVWD6R-1715569310211)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 27
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值