MFC项目如何使用hiredis库连接redis

如何在windows平台使用c++连接redis

  • 1. 下载hiredis的vs工程文件
  • 2. 使用vs2022编译hiredis
  • 3.项目中调用
  • 4. 集群连接
  • 5. 简单的封装下

最近需要在windows PC终端读取redis数据。我这里使用hiredis连接redis. 工程是vs2022开发的。

1. 下载hiredis的vs工程文件

windows平台需要自己编译hiredis这个库,这个是一个静态库,所以使用它的终端程序也要改成静态库模式。如果你的程序是用动态库的方式构架的,恭喜了,用不了, 需要自己在封装一层。

官网地址是https://github.com/redis/hiredis, 这个地址是没有vs工程的,但好心的微软提供了vs工程文件,我们直接到微软提供的地址上下载就可以https://github.com/microsoft/hiredis. 工程文件入下图
在这里插入图片描述
把整个项目都下载下来就可以。

2. 使用vs2022编译hiredis

启动vs的工程项目,工程名称见下图
在这里插入图片描述
工程就可以打开了
在这里插入图片描述
然后编译,hiredis和Win32_Interop这个两个项目就可以。
在编译Win32_Interop时可能会有报错编译不过买这个时候最简单就是将错误的地方注释掉,这边这些倒错都是报异常的代码,可以不用管。
把编译出来的lib放到一个lib目录里面
然后需要把头文件也考出来
deps\hiredies\hiredies.h
src\Win32_Interop\win32_types_hiredis.h
修改一下 hiredies.h 文件中引用 win32_types_hiredis.h 的代码:因为路径变了,将原来的注释掉
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.项目中调用

在项目中引入工厂的include目录和lib目录, 然后添加hiredis.lib,Win32_Interop.lib到以来依赖库中
在这里插入图片描述
在这里插入图片描述
然后把项目改成静态库模式
在这里插入图片描述
在这里插入图片描述
我的是MFC项目,所有MFC也要改成静态库模式
在这里插入图片描述

这样就大功告成了!!!!!!

4. 集群连接

有第3方库支持主备集群切换,但是还要自己下载编译,太太麻烦了, 直接看了原理,也就是配置多个服务器地址,连接一个服务器以后,查询下服务器的状态,是不是主的就主的就用这个连接,否在查询一个服务器地址。重连也是一样。使用命令”info replication“可以查询服务器的状态,找”role:master“这个字符串就可以了。

5. 简单的封装下

由于redisReply每次返回数据都要手动删除,直接封一个智能指针。这样就不用自己手动释放了, 我的项目都是unicode。

class AutoRedisReply
{
public:redisReply* m_pRedisReply = NULL;AutoRedisReply(){}AutoRedisReply(redisReply* pRedisReply) // Conversion constructor:m_pRedisReply(pRedisReply){}~AutoRedisReply(){Release();}void Release(){if (m_pRedisReply){freeReplyObject(m_pRedisReply);m_pRedisReply = NULL;}}void Attach(redisReply* pRedisReply){if (pRedisReply != m_pRedisReply) Release();m_pRedisReply = pRedisReply;}bool IsValid(){return m_pRedisReply != NULL;}bool IsReplyOK(){if (!m_pRedisReply) return false;return m_pRedisReply->type == REDIS_REPLY_STATUS;}bool IsReplyString(){if (!m_pRedisReply) return false;return m_pRedisReply->type == REDIS_REPLY_STRING;}std::string GetError(){std::string strError;if (!m_pRedisReply) return strError;strError = m_pRedisReply->str;return strError;}
};

redis连接类头文件

class ServerItem
{
public:std::string _strUrl;long		_nPost = 0;
};class JSRedis
{
public:JSRedis();~JSRedis();bool Connect();bool IsConnect();redisReply* PopList();bool LoadConfig();void Release();private:redisContext* m_pRedis = NULL;std::string m_strAdress;long		m_lPort = 0;std::string m_strPassword std::vector<ServerItem> m_aryServer;	//多个服务器long m_lCurServerIndex = 0;
};

cpp实现

#include "pch.h"
#include <codecvt>
#include "JSRedis.h"
#include "JSLog.h"
#include "EnvironmentVariable.h"std::wstring UTF8ToWString(const std::string& str)
{std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;return myconv.from_bytes(str);
}JSRedis::JSRedis()
{}JSRedis::~JSRedis()
{Release();
}void JSRedis::Release()
{if (m_pRedis){redisFree(m_pRedis);m_pRedis = NULL;}
}bool JSRedis::LoadConfig()
{const CString& strIni = EnvironmentVariable::GetInstance().GetIniPath();std::string strValue;TCHAR szValue[1024] = { 0 };::GetPrivateProfileString(L"Redis", L"Password", L"", szValue, ARRAYSIZE(szValue) - 1, strIni);m_strPassword = WStringToUTF8(szValue);//配置多个服务器m_aryServer.clear();int nCount= ::GetPrivateProfileInt(L"Redis", L"ServerCount", 0, strIni);CString strKey;for (int i = 0; i < nCount; ++i){ServerItem item;strKey.Format(L"Server_Url_%d",i);::GetPrivateProfileString(L"Redis", strKey, L"", szValue, ARRAYSIZE(szValue) - 1, strIni);strValue = WStringToUTF8(szValue);if (strValue.empty()) continue; item._strUrl = strValue;strKey.Format(L"Server_Port_%d", i);nValue = ::GetPrivateProfileInt(L"Redis", strKey, 0, strIni);if (nValue <= 0) continue;item._nPost = nValue;m_aryServer.push_back(item);}return true;
}bool JSRedis::Connect()
{if (m_aryServer.empty()) return false;int nIndex = m_lCurServerIndex % m_aryServer.size();const auto& item = m_aryServer[nIndex];m_strAdress = item._strUrl;m_lPort = item._nPost;TRACE_DEBUG(L"[JSRedis::Connect] start connect %s:%d, nIndex=%d", UTF8ToWString(m_strAdress).c_str(), m_lPort, nIndex);redisContext* pRedis = redisConnect(m_strAdress.c_str(), m_lPort);if (!pRedis || pRedis->err){TRACE_WARNING(L"[JSRedis::Connect] %s:%d, connect failed", UTF8ToWString(m_strAdress).c_str(), m_lPort);m_lCurServerIndex ++;if (pRedis) redisFree(pRedis);return false;}{AutoRedisReply reply = (redisReply*)redisCommand(pRedis, "AUTH %s", m_strPassword.c_str());if (!reply.IsValid()){redisFree(pRedis);return false;}if (!reply.IsReplyOK()){TRACE_WARNING(L"[JSRedis::Connect] %s:%d, password error.", UTF8ToWString(m_strAdress).c_str(), m_lPort);redisFree(pRedis);return false;}}{	//查询主从AutoRedisReply reply = (redisReply*)redisCommand(pRedis, "info replication");if (!reply.IsValid()){redisFree(pRedis);return false;}if (!reply.IsReplyString()){m_lCurServerIndex++;redisFree(pRedis);return false;}std::string strInfo = reply.m_pRedisReply->str;TRACE_NORMAL(L"[JSRedis::Connect] %s:%d,info replication:%s ", UTF8ToWString(m_strAdress).c_str(), m_lPort, UTF8ToWString(strInfo).c_str());if (strInfo.find("role:master") == std::string::npos)	//从的过滤掉{TRACE_WARNING(L"[JSRedis::Connect] %s:%d, is not 'role:master'.", UTF8ToWString(m_strAdress).c_str(), m_lPort);m_lCurServerIndex++;redisFree(pRedis);return false;}}{AutoRedisReply reply = (redisReply*)redisCommand(pRedis, "select %d", 12);if (!reply.IsValid()){redisFree(pRedis);return false;}if (!reply.IsReplyOK()){TRACE_WARNING(L"[JSRedis::Connect] %s:%d, select 12 error.", UTF8ToWString(m_strAdress).c_str(), m_lPort);redisFree(pRedis);return false;}}m_pRedis = pRedis;TRACE_DEBUG(L"[JSRedis::Connect] connect %s:%d success, nIndex=%d", UTF8ToWString(m_strAdress).c_str(), m_lPort, nIndex);return true;
}bool JSRedis::IsConnect()
{return m_pRedis != NULL;
}redisReply* JSRedis::PopList()
{std::string strKey = "队列名字"return (redisReply*)redisCommand(m_pRedis, "RPOP %s", strKey.c_str());
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1559283.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【C/C++】错题记录(七)

题目一 题目二 C在调用函数时&#xff0c;当实参和形参的数据类型不一致时&#xff0c;会发生数据类型转换&#xff01;将低精度转换为高精度时&#xff0c;由编译器隐式完成&#xff1b;将高精度转换为低精度时&#xff0c;必须用强制类型转换运算符&#xff1b; static_cast…

Redis:分布式 - 哨兵

Redis&#xff1a;分布式 - 哨兵 概念哨兵 Docker 搭建哨兵分布式选举流程 概念 Redis 的主从复制模式下&#xff0c;一旦主节点由于故障不能提供服务&#xff0c;需要人工进行主从切换&#xff0c;同时大量的客户端需要被通知切换到新的主节点上&#xff0c;对于上了一定规模…

浏览器动态移动的小球源码分享

浏览器动态移动的小球源码分享 <script>(function(a){var width100,height100,borderRadius100,circlefunction(){};circle.prototype{color:function(){let colour "#"Math.floor(Math.random()*255).toString(16)Math.floor(Math.random()*255).toString…

Linux块设备驱动实验

直接参考【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.81 本文仅作为个人笔记使用&#xff0c;方便进一步记录自己的实践总结。 前面我们都是在学习字符设备驱动&#xff0c;本章我们来学习一下块设备驱动框架&#xff0c;块设备驱动是Linux 三大驱动类型之一。块设备驱动要远…

Fiddler配合wireshark解密ssl

环境&#xff1a; win11&#xff08;wireshark&#xff09;--虚拟机win7&#xff08;Fiddler&#xff09;---虚拟机win7&#xff08;HTTPS站点&#xff09; 软件安装问题&#xff1a; 需要.net环境&#xff0c;NDP461-KB3102436-x86-x64-AllOS-ENU.exe。 安装fiddler后安装下…

vite项目打包md5报‘default‘ is not exported错误的解决方法

报错如下&#xff1a; 某一个包中用es方式引入md5模块&#xff0c;导致打包报错&#xff0c;经过一番探究测试&#xff0c;发现我的项目中用了“vite-plugin-require-transform”这个插件&#xff0c;是这个插件在做转换的时候报错了&#xff0c;如果你也是这个原因可按我的方式…

代码随想录day24:贪心part2

121. 买卖股票的最佳时机 class Solution {public int maxProfit(int[] prices) {int ans 0;int minPrice prices[0];for(int p : prices){ans Math.max(ans, p - minPrice);minPrice Math.min(p, minPrice);}return ans;} } 运用前缀和思想&#xff0c; 从左到右枚举卖…

Spring Boot教学资源库:构建微服务的基石

2 相关技术简介 2.1Java技术 Java是一种非常常用的编程语言&#xff0c;在全球编程语言排行版上总是前三。在方兴未艾的计算机技术发展历程中&#xff0c;Java的身影无处不在&#xff0c;并且拥有旺盛的生命力。Java的跨平台能力十分强大&#xff0c;只需一次编译&#xff0c;任…

dart-sass和node-sass的区别,使用dart-sass后可能会出现的问题

前言&#xff1a; 2020 年 10 月 27 日&#xff0c;Sass 官方团队正式宣布 Libsass 将弃用&#xff0c;以及基于它的 Node Sass 和 SassC&#xff0c;并且建议用户使用 Dart Sass。如果在 vue 脚手架搭建的项目中需要使用 sass&#xff0c;建议初始化时勾选 sass 配置&#xff…

前端优化之路:git commit 校验拦截

但是想要做到高效落地执行&#xff0c;就需要做些别的功课&#xff0c;先展示下成果图 需要了解git hooks&#xff0c;它是git的钩子&#xff0c;就像vue拥有自己的钩子一样。 官方文档&#xff1a;https://git-scm.com/docs/githooks 项目安装 husky&#xff0c;建议稳定版本…

patch函数前两个参数位

如我们多了解的&#xff0c;patch函数前两个参数位为 oldVnode 和 Vnode &#xff0c;分别代表旧节点和新节点&#xff0c;主要做了四个判断&#xff1a; patchVnode主要做了两个判断&#xff1a;

java中Math类和Random类的api

目录 Math 类 1&#xff09;abs(x) 2&#xff09;ceil(x) 3&#xff09;floor(x) 4&#xff09;round(x) 5&#xff09;max(x, y) 6&#xff09;min(x, y) 7&#xff09;sqrt(x) 8&#xff09;pow(x, y) 9&#xff09;random() 10&#xff09;sin(x), cos(x), tan(x) 11&#x…

购物网站毕业设计-电子电器商城管理系统SpringBootSSM框架开发

目录 1. 系统概述 1.1背景介绍 1.2 课题意义 1.3课题目标 2. 主要功能模块 2.1 前端用户模块 2.2 后端管理模块 2.3 功能图展示 3. 技术选型 3.1 VUE介绍 3.2 JAVA介绍 3.3 MySQL介绍 4. 系统设计 4‌.1数据库设计 5 详细设计 5.1 界面展示 设计一个电子电…

通过Keil5编译软件获取函数最深堆栈

文章目录 1.问题提出2.问题分析3.环境搭建4.解决方案5.经验总结6.疑问 1.问题提出 在编写新软件时&#xff0c;由于某功能需要使用RAM约24KB&#xff0c;而新模块的总RAM是96KB&#xff0c;该某功能一旦开启则需要占用四分之一的RAM空间。为了保证在开启某功能后&#xff0c;新…

WPF中的Window类

控件分类 在第一篇文章.Net Core和WPF介绍中的WPF的功能和特性部分根据功能性介绍了WPF的控件 名称。 在接下来的文章中&#xff0c;将会详细的介绍各个控件的概念及使用。 主要包括&#xff1a; 内容控件&#xff1a;Label、Button、CheckBox、ToggleButton、RadioButton、…

高性能缓存方案 —— Caffeine

一、简介 Caffeine是一个高性能的Java缓存库&#xff0c;它提供了本地缓存的功能。 Caffeine和Redis都是内存级别的缓存&#xff0c;为什么要使用在这两缓存作为二级缓存&#xff0c;它们两有什么区别呢? 虽然它们都是内存级别的缓存&#xff0c;但是Redis是需要单独部署的&…

【开源风云】从若依系列脚手架汲取编程之道(五)

&#x1f4d5;开源风云系列 &#x1f34a;本系列将从开源名将若依出发&#xff0c;探究优质开源项目脚手架汲取编程之道。 &#x1f349;从不分离版本开写到前后端分离版&#xff0c;再到微服务版本&#xff0c;乃至其中好玩的一系列增强Plus操作。 &#x1f348;希望你具备如下…

鸿蒙OS投票机制

(基于openharmony5.0) 投票机制 param get | grep ohos.boot.time 图 投票机制参数图 只有当所有的投票完成&#xff0c;开机动画才会退出&#xff0c;整理需要投票的系统应用&#xff08;三方应用不参与投票&#xff09;如下图所示&#xff1a; 以进程foundation为例&…

Python案例--copy复制

在Python编程中&#xff0c;数据的复制是一个常见且重要的操作&#xff0c;它涉及到赋值、浅拷贝和深拷贝三种不同的概念。正确理解这三种操作对于编写高效且正确的程序至关重要。本文将通过一个简单的Python示例&#xff0c;探讨这三种数据复制方式的区别及其应用场景&#xf…

计算机视觉之OpenCV vs YOLO

好多开发者希望搞明白OpenCV 和YOLO区别&#xff0c;实际上&#xff0c;二者在计算机视觉领域都有广泛应用&#xff0c;但它们有很大的不同。 一、OpenCV 概述 OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉和机器学习软件库。它…