redis,总想着像Mysql一样,在C/C++中进行对接。于是查询了一些资料,最后找到了hiredis。然而直接用它的话,难免有点不方便。于是,对其进行封装。

hiredis直接去git上克隆,地址:https://github.com/redis/hiredis。

下载好之后,由于其自带Makefile,只要make一下就编译出静态库与动态库了,接着把头文件和静/动态库放在相应的文件夹里就可以了。注意如果使用动态库,而且是放在/usr/local/lib/里,得执行ldconfig命令,来更新一下配置,或者得配置一下动态库路径。

安装好了就是如何使用的事了。

学习hiredis主要是参考这两个链接:

http://blog.csdn.net/gqtcgq/article/details/51344232

http://blog.csdn.net/achelloworld/article/details/41598389?utm_source=tuicool&utm_medium=referral

文章给大家分享C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK技术,面试技巧方面的资料分享的https://ke.qq.com/course/417774?flowToken=1011069

一共就五个函数。

1、redisContext* redisConnect(const char *ip, int port)2、redisContext* redisConnectWithTimeout(const char *ip, int port, timeval tv)3、void redisFree(redisContext *c)4、void *redisCommand(redisContext *c, const char *format...)5、void freeReplyObject(void *reply)

和Mysql一样,要对接,第一件事就是用IP和端口号建立连接什么的。redis的端口号一般是6379,IP直接用127.0.0.1就可以了。既然要用到IP和端口号,又是可能会变的东西,为了不使想要改变它们的时候得直接修改代码,我写了个配置文件:

redisConf.json

1 {

2    "IP" : "127.0.0.1" ,

3    "PORT" : 6379

4 }

相应地,有提取配置信息的类

redisConf.h

1 #ifndef __REDISCONF_H__

2 #define __REDISCONF_H__

3 #include

4 namespace ccx{

5 using std::string;

6 class RedisConf

7 {

8    public:

9        RedisConf();

10        void getConf();

11        string getIP();

12        int getPort();

13    private:

14        string _ip;

15        int _port;

16 };

17 }

18 #endif

redisconf.cc

1 #include "redisConf.h"

2 #include

3 #include

4 #include

5 #include

6 #include

7

8 namespace ccx{

9

10 using std::ifstream;

11 using std::cout;

12 using std::endl;

13

14 RedisConf::RedisConf()

15 {

16    getConf();

17 }

18

19 void RedisConf::getConf()

20 {

21    ifstream ifs;

22    ifs.open("redisConf.json");

23    if(!ifs.good())

24    {

25        cout << "open RedisConf.json error" << endl;

26        exit(EXIT_FAILURE);

27    }

28

29    Json::Value root;

30    Json::Reader reader;

31    if(!reader.parse(ifs, root, false))

32    {

33        cout << "RedisConf json reader error" << endl;

34        exit(EXIT_FAILURE);

35    }

36

37    _ip = root["IP"].asString();

38    _port = root["PORT"].asInt();

39    ifs.close();

40 }

41

42 string RedisConf::getIP()

43 {

44    return _ip;

45 }

46

47 int RedisConf::getPort()

48 {

49    return _port;

50 }

51

52 }

然后是目前的redis类:

redis.h

1 #ifndef __REDIS_H__

2 #define __REDIS_H__

3

4 #include "redisConf.h"

5

6 #include

7

8

9 namespace ccx{

10

11 class Redis

12 {

13    public:

14        Redis();

15    public:

16        void Connect();

17        void disConnect();

18    public:

19        void setString(const string & key, const string & value);

20        void setString(const string & key, const int & value);

21        void setString(const string & key, const float & value);

22    private:

23        void setString(const string & data);

24    public:

25        void getString(const string & key, string & value);

26        void getString(const string & key, int & value);

27        void getString(const string & key, float & value);

28    private:

29        void getString(const string & key);

30    private:

31        void freeReply();

32        bool isError();

33    private:

34        RedisConf _conf;

35        redisContext * _context;

36        redisReply * _reply;

37 };

38 }

39

40 #endif下面结合写好的代码说说前面的五个函数。

函数1是用来连接redis的,具体如下:1 void Redis::Connect()

2 {

3    _context = ::redisConnect(_conf.getIP().c_str(), _conf.getPort());

4    cout << _conf.getIP() << "-" << _conf.getPort() << endl;

5    if(_context && _context->err)

6    {

7        cout << "connect redis error" << endl;

8        exit(EXIT_FAILURE);

9    }

10    cout << "redis Connect success" << endl;

11 }

函数2是在1的基础上,添加了一个超时功能。

函数3是在不使用redis了,要断开连接时使用的:

1 void Redis::disConnect()

2 {

3    ::redisFree(_context);

4    cout << "redis disConnect success" << endl;

5 }

函数4稍微复杂一些,有点像C中的printf:

1 printf("%d%s%d",d1,s1,d2);

2 printf("hello,world");

可以这样用:

1 char * command = "SET name lili";

2 reply = (redisReply*)::redisCommand(context, command);

3 char * s1 = "name";

4 char * s2 = "lili";

5 reply = (redisReply*)::redisCommand(context, "SET %s %s", s1, s2);

6 reply = (redisReply*)::redisCommand(context, "SET name lili");

7 ...

第一个参数context是函数1或者2的返回值,告诉它要与哪里的redis进行交互。reply指向命令结果的存储位置。

函数5是用来清理函数4 的返回结果的:

1 void Redis::freeReply()

2 {

3    if(_reply)

4    {

5        ::freeReplyObject(_reply);

6        _reply = NULL;

7    }

8 }

第6行是因为对这个函数不熟,就干脆清完之后给它赋值NULL。

由于redis的string中存的可能是字符串、整形、浮点数,于是各自重载了三个版本的get与set方法,并重用一些函数,以减少代码量。

对于set,直接用一个宏替换:

1 #define SETSTRING(key, value) \

2    stringstream ss;\

3    ss << "SET " << key << " " << value;\

4    string s;\

5    getline(ss, s);\

6    setString(s);

1 void Redis::setString(const string & key, const string & value)

2 {

3    SETSTRING(key, value);

4 }

5 void Redis::setString(const string & key, const int & value)

6 {

7    SETSTRING(key, value);

8 }

9 void Redis::setString(const string & key, const float & value)

10 {

11    SETSTRING(key, value);

12 }

使用C++中的stringstream,会比用“%d”、“%s”、“%f”来区分类型少些代码。两种方法的结果是相同的。

它们共用的setString方法:

1 void Redis::setString(const string & data)

2 {

3    freeReply();

4    _reply = (redisReply*)::redisCommand(_context, data.c_str());

5    if(!isError())

6    {

7        if (!(_reply->type == REDIS_REPLY_STATUS && strcasecmp(_reply->str,"OK") == 0))

8        {

9            cout << "Failed to execute SET(string)" << endl;

10        }

11    }

12 }

这里的isError是用来判断是否连接异常的:

1 bool Redis::isError()

2 {

3    if(NULL == _reply)

4    {

5        freeReply();

6        disConnect();

7        Connect();

8        return true;

9    }

10    return false;

11 }

如果连接异常,得断开重连。

在redis命令行里,如果set成功,会提示“OK”。于是,这里先判断了一下命令结果的数据类型,如果是字符串,再判断它是不是“OK”,以此来判断set是否成功。

对于get,我试了各种方法,都无法直接从命令结果中提取出数字,暂时还没找到原因。但是数字却可以以字符串格式得到。于是,使用了atoi来处理:

1 void Redis::getString(const string & key)

2 {

3    freeReply();

4    _reply = (redisReply*)::redisCommand(_context, "GET %s", key.c_str());

5 }

6

7 void Redis::getString(const string & key, string & value)

8 {

9    getString(key);

10    if(!isError() && _reply->type == REDIS_REPLY_STRING)

11    {

12        value = _reply->str;

13    }

14 }

15

16 void Redis::getString(const string & key, int & value)

17 {

18    getString(key);

19    if(!isError() && _reply->type == REDIS_REPLY_STRING)

20    {

21        value = ::atoi(_reply->str);

22    }

23 }

24

25 void Redis::getString(const string & key, float & value)

26 {

27    getString(key);

28    if(!isError() && _reply->type == REDIS_REPLY_STRING)

29    {

30        value = ::atof(_reply->str);

31    }

32 }

redis.cc

View Code

test.cc

View Code

测试结果如下:

127.0.0.1-6379

redis Connect success

lii

30

30

redis disConnect success

linux c 封装redis,封装hiredis——C++与redis对接(一)(string的SET与GET操作)相关推荐

  1. linux socket通信出错封装处理

    linux socket通信出错封装处理 wrap.c #include <stdlib.h> #include <errno.h> #include <sys/sock ...

  2. linux hiredis yum,Centos7 安装Redis和Hiredis

    一.安装Redis 1.先安装tclyum -y install tclwget http://download.redis.io/releases/redis-3.0.7.tar.gz tar xz ...

  3. redis 使用-hiredis库使用(一) 基本篇 看完本文就可以上手工作了

    hiredis是redis的客户端sdk,可以让程序操作redis.本文先将建立连接,基本的get/set命令,读写二进制,获取多个结果来讲.假设读者已经了解redis命令了. hiredis的代码也 ...

  4. linux下搭建redis并解决无法连接redis的问题

    linux下搭建redis并解决无法连接redis的问题 参考文章: (1)linux下搭建redis并解决无法连接redis的问题 (2)https://www.cnblogs.com/bestmy ...

  5. 【Linux】【服务器】 CentOS7下安装Redis详细过程步骤

    Linux 源码安装 一.下载地址:http://redis.io/download,下载最新稳定版本. # wget http://download.redis.io/releases/redis- ...

  6. windows下redis 和 hiredis的编译与使用

    编译环境,32位windows7,VS2013 获取redis windows版 MS Open Technologies 官方主页 GitHub上的MSOpenTech/redis项目地址 编译 r ...

  7. linux redis客户端_为什么单线程Redis能那么快?

    我们通常说,Redis 是单线程,主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的,这也是 Redis 对外提供键值存储服务的主要流程.但 Redis 的其他功能,比如持久化.异步 ...

  8. Linux服务器运行环境搭建(二)——Redis数据库安装

    官网地址:http://redis.io/ 官网下载地址:http://redis.io/download 1. 下载Redis源码(tar.gz),并上传到Linux 2. 解压缩包:tar zxv ...

  9. 什么叫封装?封装有什么作用?

    一.什么是封装? 封装是把彼此相关数据和操作包围起来,抽象成为一个对象,变量和函数就有了归属,想要访问对象的数据只能通过已定义的接口. 说封装就是将属性私有化,太过狭隘,因为封装不仅仅实现了数据的保护 ...

最新文章

  1. 在IBatisNet中使用存储过程
  2. 中兴智能视觉大数据报:要注意,人工智能将衍生更多工作机会
  3. Cannot find module 'express'
  4. 把Python程序的输出和异常信息自动写入文件
  5. 位、字、字节的区别 | 汇编伪指令db,dw,dd
  6. base cap 分布式_分布式系统一致性问题、CAP定律以及 BASE 理论
  7. 试卷分析计算机基础,计算机基础试卷分析.doc
  8. 软件项目经理(实施)流程经验及理解
  9. dw如何制作图片自动切换效果_如何在DREAMWEAVER中做出图片切换效果?
  10. 故障分析 | OceanBase Proxy 无法连接 OBserver 集群
  11. 计算机桌面 文字大小,电脑屏幕字体怎么调大小_电脑系统字体大小设置方法-win7之家...
  12. java利用Scanner获取键盘输入
  13. 2023年最热门的网络安全岗位分析
  14. 六边形算法java_六边形架构 Java 实现
  15. 请评价一下中国的东北大学计算机水平如何
  16. Hadoop 调优之Linux操作系统调优篇
  17. 工业物联网时代 智能化可以分阶段快速部署
  18. 维密超模也来学编程?你想象得到吗,这些明星也曾是程序员!
  19. 打造手机上的移动影院,爱奇艺「帧绮映画」要引领超清变革
  20. Day1-JSP的入门了解以及环境的配置Tomcat的注意点和一些常见问题的解决方案(适宜JSPServlet的初学者的学习)

热门文章

  1. python ftplib bufsize_python:ftplib模块
  2. layui tree 加载慢_图片太多,加载慢,我用了layui里的方式,放在服务器后还是太慢!怎么解决???有没有什么优化的技巧???...
  3. python upper_Python 3中的模块级string.upper函数在哪里?
  4. 给mysql数据库设计编码_MYSQL数据库编码原理
  5. 请求头Content-Type:application/json,java后端如何接收数据
  6. python判断两个列表内容是否一致_检查两个列表在Python中是否相同
  7. mysql data transfer_MySQL主从同步加速 Transfer-- FAQ
  8. 事务超时时间无效_什么是ZooKeeper?ZooKeeper分布式事务详解
  9. 计算机主机声音怎么办,电脑主机声音大怎么解决 电脑主机嗡嗡响是怎么回事...
  10. netty冲突 play sbt_《Netty官方文档》本地传输接口