redis使用c++ API 的hiredis连接详解

redis使用c++ API 的hiredis连接详解Redis 是一个 NoSQL 数据库 本文将实现一个用 c API 接口连接的例子 来实现对 Redis 数据库的写入和读出功能 具体将从 Redis 的安装 Redis 的 c 接口 hiredis 安装 代码演示三部分组成 一 Redis 的安装和配置由于源中已有 Redis 的相关组件 这里就不进行源码编译而直接使用 apt get ubuntu 环境 下载和安装 1 redis 的安装和配

    Redis是一个NoSQL数据库,本文将实现一个用c++ API接口连接的例子,来实现对Redis数据库的写入和读出功能,具体将从Redis的安装,Redis的c++接口hiredis安装,代码演示三部分组成。

一、Redis的安装和配置

    由于源中已有Redis的相关组件,这里就不进行源码编译而直接使用apt-get (ubuntu环境)下载和安装

1.redis的安装和配置 sudo apt-cache search redis //根据结果列表找到需要安装的软件包:redis-server sudo apt-get install redis-server //安装软件 2.配置文件 whereis resids //查看redis位置: /etc/redis cd /etc/redis //进入文件夹 /etc/redis$ ls -l //显示文件,其中redis.conf为配置文件 总用量 60 -rw-r----- 1 redis redis 41623 12月 19 2015 redis.conf drwxr-xr-x 2 root root 4096 9月 21 10:47 redis-server.post-down.d drwxr-xr-x 2 root root 4096 9月 21 10:47 redis-server.post-up.d drwxr-xr-x 2 root root 4096 9月 21 10:47 redis-server.pre-down.d drwxr-xr-x 2 root root 4096 9月 21 10:47 redis-server.pre-up.d 3.启动 服务端:redis-server (使用默认端口) (--port 6599 加端口) 客户端:redis-cli (连接之前测试启动指令 redis-cli ping 返回PONG启动成功) 4.关闭:redis-cli (-p 6380 可指定端口)shutdown

二、redis的c++api接口 hiredis安装

    实际上hiredis是一个c的接口,同样使用apt-get安装hiredis,GitHub上有他的完整工程项目,点此转到

sudo apt-cache search hiredis // 查看发现c语言开发库为libhiredis-dev libhiredis-dbg - minimalistic C client library for Redis (debug) libhiredis-dev - minimalistic C client library for Redis (development files) libhiredis0.13 - minimalistic C client library for Redis python-hiredis - redis protocol reader for Python 2.X using hiredis sudo apt-get install libhiredis-dev //选择并安装

     hiredis库目录的位置为默认的 /usr/lib/x86_64-linux-gnu/下,头文件在 /usr/include/hiredis 下,hiredis头文件中定义了Redis的连接的方式redisConnect()等方法,连接信息存储在上下文redisContext的结构体对象中,通过redisCommand()等方法进行具体的数据库存取指令操作并返回相关信息在redisReply的结构体对象中,不要忘了freeReplyObject(void *reply)释放redisReply连接响应对象,redisFree()函数释放redisContext上下文对象,具体的定义和方法请看以下代码。

#ifndef __HIREDIS_H #define __HIREDIS_H #include "read.h" #include 
  
    /* for va_list */ #include 
   
     /* for struct timeval */ #include 
    
      /* uintXX_t, etc */ #include "sds.h" /* for sds */ #define HIREDIS_MAJOR 0 #define HIREDIS_MINOR 13 #define HIREDIS_PATCH 3 #define HIREDIS_SONAME 0.13 #ifdef __cplusplus extern "C" { #endif /* This is the reply object returned by redisCommand() 执行redis数据库指令操作的响应信息封装在redisReply的结构体中 */ typedef struct redisReply { int type; /* REDIS_REPLY_* */ long long integer; /* The integer when type is REDIS_REPLY_INTEGER */ int len; /* Length of string 存储字符串长度 */ char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING 错误信息和返回的string类型*/ size_t elements; /* number of elements, for REDIS_REPLY_ARRAY 如果为数组存储数组长度*/ struct redisReply element; /* elements vector for REDIS_REPLY_ARRAY 存储数组元素向量*/ } redisReply; redisReader *redisReaderCreate(void); /* Function to free the reply objects hiredis returns by default. 释放响应对象 */ void freeReplyObject(void *reply); /* Functions to format a command according to the protocol. 数据库操作相关语句 */ int redisvFormatCommand(char target, const char *format, va_list ap); int redisFormatCommand(char target, const char *format, ...); int redisFormatCommandArgv(char target, int argc, const char argv, const size_t *argvlen); int redisFormatSdsCommandArgv(sds *target, int argc, const char argv, const size_t *argvlen); void redisFreeCommand(char *cmd); void redisFreeSdsCommand(sds cmd); enum redisConnectionType { REDIS_CONN_TCP, REDIS_CONN_UNIX, }; /* Context for a connection to Redis 建立上下文连接对象的结构体 */ typedef struct redisContext { int err; /* Error flags, 0 when there is no error错误标志,0表示没有错误 */ char errstr[128]; /* String representation of error when applicable 错误声明 */ int fd; int flags; char *obuf; /* Write buffer */ redisReader *reader; /* Protocol reader */ enum redisConnectionType connection_type; struct timeval *timeout; //设置连接等待时间 struct { char *host; char *source_addr; int port; } tcp; struct { char *path; } unix_sock; } redisContext; //建立上下文连接 redisContext *redisConnect(const char *ip, int port); redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv); redisContext *redisConnectNonBlock(const char *ip, int port); redisContext *redisConnectBindNonBlock(const char *ip, int port, const char *source_addr); redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port, const char *source_addr); redisContext *redisConnectUnix(const char *path); redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv); redisContext *redisConnectUnixNonBlock(const char *path); redisContext *redisConnectFd(int fd); / * Reconnect the given context using the saved information. * * This re-uses the exact same connect options as in the initial connection. * host, ip (or path), timeout and bind address are reused, * flags are used unmodified from the existing context. * * Returns REDIS_OK on successfull connect or REDIS_ERR otherwise. */ int redisReconnect(redisContext *c); int redisSetTimeout(redisContext *c, const struct timeval tv); int redisEnableKeepAlive(redisContext *c); void redisFree(redisContext *c); int redisFreeKeepFd(redisContext *c); int redisBufferRead(redisContext *c); int redisBufferWrite(redisContext *c, int *done); /* In a blocking context, this function first checks if there are unconsumed * replies to return and returns one if so. Otherwise, it flushes the output * buffer to the socket and reads until it has a reply. In a non-blocking * context, it will return unconsumed replies until there are no more. */ int redisGetReply(redisContext *c, void reply); int redisGetReplyFromReader(redisContext *c, void reply); /* Write a formatted command to the output buffer. Use these functions in blocking mode * to get a pipeline of commands. */ int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len); /* Write a command to the output buffer. Use these functions in blocking mode * to get a pipeline of commands. */ int redisvAppendCommand(redisContext *c, const char *format, va_list ap); int redisAppendCommand(redisContext *c, const char *format, ...); int redisAppendCommandArgv(redisContext *c, int argc, const char argv, const size_t *argvlen); /* Issue a command to Redis. In a blocking context, it is identical to calling * redisAppendCommand, followed by redisGetReply. The function will return * NULL if there was an error in performing the request, otherwise it will * return the reply. In a non-blocking context, it is identical to calling * only redisAppendCommand and will always return NULL. */ void *redisvCommand(redisContext *c, const char *format, va_list ap); void *redisCommand(redisContext *c, const char *format, ...); void *redisCommandArgv(redisContext *c, int argc, const char argv, const size_t *argvlen); #ifdef __cplusplus } #endif #endif 
     
    
  

    在read.h文件中有redisReply结构体宏的定义,int type的类型:

#ifndef __HIREDIS_READ_H #define __HIREDIS_READ_H #define REDIS_ERR -1 #define REDIS_OK 0 #define REDIS_ERR_IO 1 /* Error in read or write */ #define REDIS_ERR_EOF 3 /* End of file */ #define REDIS_ERR_PROTOCOL 4 /* Protocol error */ #define REDIS_ERR_OOM 5 /* Out of memory */ #define REDIS_ERR_OTHER 2 /* Everything else... */ #define REDIS_REPLY_STRING 1 //存放在char *str #define REDIS_REPLY_ARRAY 2 #define REDIS_REPLY_INTEGER 3 //integer存储为数据条数 #define REDIS_REPLY_NIL 4 #define REDIS_REPLY_STATUS 5 //成功状态码为:"OK" 存放在char *str #define REDIS_REPLY_ERROR 6 //存放在char *str

redis使用c++ API 的hiredis连接详解

     如hiredis.c文件中看freeReplyObject函数对以上响应状态的处理:

/* Free a reply object redisReply的类型有:REDIS_REPLY_INTEGER: REDIS_REPLY_ERROR: REDIS_REPLY_STATUS: REDIS_REPLY_STRING:这三个都是返回字符串 */ void freeReplyObject(void *reply) { redisReply *r = reply; size_t j; if (r == NULL) return; switch(r->type) { case REDIS_REPLY_INTEGER: break; /* Nothing to free */ case REDIS_REPLY_ARRAY: if (r->element != NULL) { for (j = 0; j < r->elements; j++) freeReplyObject(r->element[j]); free(r->element); } break; case REDIS_REPLY_ERROR: case REDIS_REPLY_STATUS: case REDIS_REPLY_STRING: free(r->str); break; } free(r); }

三、Redis使用hiredis API连接

代码结构如图所示:

redis使用c++ API 的hiredis连接详解

具体代码如下:配置文件

#ifndef REDISCONFIG_H #define REDISCONFIG_H #include 
  
    class RedisConfig { public: RedisConfig(); std::string getRedisIP();//获取ip int getRedisPort();//获取端口号 }; #endif 
  
#include "RedisConfig.h" #include 
  
    RedisConfig::RedisConfig() { } std::string RedisConfig::getRedisIP() { return "127.0.0.1";//设置为本机ip } int RedisConfig::getRedisPort() { return 6379; } 
  

    具体处理代码:包含了string类型和list类型的存取代码,根据redisReply响应的信息来进行信息的处理,对于其他类型对响应状态的判断可以通过命令行操作来确定,如图1所示。

#ifndef _H_REDIS_TOOLS_ #define _H_REDIS_TOOLS_ #include 
  
    #include 
   
     #include 
    
      #include 
     
       using namespace std; class RedisTool { public: RedisTool(); ~RedisTool(); int setString(string key, string value); string getString(string key); int setList(string key,vector 
      
        value); vector 
       
         getList(string key); private: void init(); redisContext *m_redis; RedisConfig m_config; }; #endif 
        
       
      
     
    
  
#include 
  
    #include 
   
     #include 
    
      #include 
     
       #include 
      
        RedisTool::RedisTool() { m_redis = NULL; init(); } RedisTool::~RedisTool() { if(m_redis != NULL) { redisFree(m_redis);//析构函数释放资源 cout << "~RedisTool :: free redis connection " << endl; } } void RedisTool::init() { struct timeval timeout = { 1, }; // 1.5 seconds 设置连接等待时间 char ip[255]; strcpy(ip, m_config.getRedisIP().c_str()); cout << "init : ip = " << ip << endl; m_redis = redisConnectWithTimeout(ip, m_config.getRedisPort(), timeout);//建立连接 if (m_redis->err) { printf("RedisTool : Connection error: %s\n", m_redis->errstr); } else { cout << "init redis tool success " << endl; //REDIS_REPLY响应的类型type cout << "#define REDIS_REPLY_STRING 1"<< endl; cout << "#define REDIS_REPLY_ARRAY 2"<< endl; cout << "#define REDIS_REPLY_INTEGER 3"<< endl; cout << "#define REDIS_REPLY_NIL 4"<< endl; cout << "#define REDIS_REPLY_STATUS 5"<< endl; cout << "#define REDIS_REPLY_ERROR 6"<< endl; } } //向数据库写入string类型数据 int RedisTool::setString(string key, string value) { if(m_redis == NULL || m_redis->err)//int err; /* Error flags, 错误标识,0表示无错误 */ { cout << "Redis init Error !!!" << endl; init(); return -1; } redisReply *reply; reply = (redisReply *)redisCommand(m_redis,"SET %s %s", key.c_str(), value.c_str());//执行写入命令 cout<<"set string type = "< 
       
         type< 
        
          str = NULL " << endl; //pthread_spin_unlock(&m_redis_flock); return -1; } else if(strcmp(reply->str, "OK") == 0)//根据不同的响应类型进行判断获取成功与否 { result = 1; } else { result = -1; cout << "set string fail :" << reply->str << endl; } freeReplyObject(reply);//释放响应信息 return result; } //从数据库读出string类型数据 string RedisTool::getString(string key) { if(m_redis == NULL || m_redis->err) { cout << "Redis init Error !!!" << endl; init(); return NULL; } redisReply *reply; reply = (redisReply *)redisCommand(m_redis,"GET %s", key.c_str()); cout<<"get string type = "< 
         
           type< 
          
            len <= 0) { freeReplyObject(reply); return NULL; } else { stringstream ss; ss << reply->str; freeReplyObject(reply); return ss.str(); } } //向数据库写入vector(list)类型数据 int RedisTool::setList(string key,vector 
           
             value) { if(m_redis == NULL || m_redis->err) { cout << "Redis init Error !!!" << endl; init(); return -1; } redisReply *reply; int valueSize = value.size(); int result = 0; for(int i=0; i 
            
              integer; if(reply == NULL) { redisFree(m_redis); m_redis = NULL; result = -1; cout << "set list fail : reply->str = NULL " << endl; //pthread_spin_unlock(&m_redis_flock); return -1; } else if(reply->integer == old++) { result = 1; cout<<"rpush list ok"< 
             
               integer = " << reply->integer << endl; return -1; } } freeReplyObject(reply); cout<<"set List success"< 
              
                RedisTool::getList(string key) { if(m_redis == NULL || m_redis->err) { cout << "Redis init Error !!!" << endl; init(); return vector 
               
                 {};//返回空的向量 } redisReply *reply; reply = (redisReply*)redisCommand(m_redis,"LLEN %s", key.c_str()); int valueSize = reply->integer; cout<<"List size is :"< 
                
                  integer< 
                  
                 
                
               
              
             
            
           
          
         
        
       
      
     
    
  

    main函数:

#include 
  
    #include 
   
     #include 
    
      using namespace std; int main() { RedisTool redis; //测试 string redis.setString("wangbaojia","test1"); string result = redis.getString("wangbaojia"); cout<<"result="< 
     
       vec ={1,2,3,4}; redis.setList("bao",vec); vector 
      
        vecResult = redis.getList("bao"); for(int i=0;i 
        
       
      
     
    
  

      运行结果:

redis使用c++ API 的hiredis连接详解

 四、完整代码下载   

点击下载                                                                  

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/228165.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午7:40
下一篇 2026年3月16日 下午7:40


相关推荐

  • 悲观锁和乐观锁的使用[通俗易懂]

    悲观锁和乐观锁的使用[通俗易懂]1、悲观锁(PessimisticLock),顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。最常用的就是select..forupdate,它是一种行锁,会把select出来的结果行锁住,在本

    2022年8月23日
    10
  • 五种聚类方法_聚类分析是一种降维方法吗

    五种聚类方法_聚类分析是一种降维方法吗本文为雷锋字幕组编译的技术博客,原标题The5ClusteringAlgorithmsDataScientistsNeedtoKnow,作者为GeorgeSeif。聚类是一种关于数据点分组的机器学习技术。给出一组数据点,我们可以使用聚类算法将每个数据点分类到特定的组中。理论上,同一组中的数据点应具有相似的属性或特征,而不同组中的数据点应具有相当不同的属性或特征(即类内差异小,…

    2022年10月20日
    5
  • 元宝跟微信是什么关系?

    元宝跟微信是什么关系?

    2026年3月12日
    2
  • 四种主流聚类方法

    四种主流聚类方法四种聚类方法之比较 2015 07 29 nbsp SOTON 数据分析聚类分析是一种重要的人类行为 早在孩提时代 一个人就通过不断改进下意识中的聚类模式来学会如何区分猫狗 动物植物 目前在许多领域都得到了广泛的研究和成功的应用 如用于模式识别 数据分析 图像处理 市场研究 客户分割 Web 文档分类等 1 聚类就是按照某个特定标准 如距离准则 即数据点之间的距离 把一个数据集分

    2026年3月26日
    3
  • Aras 修改正则表达式验证时,错误的提示信息

    Aras 修改正则表达式验证时,错误的提示信息1 添加 List 名称为 StringFormat 用于管理 String 类型中用到的所有的判断正则表达式 如下 2 添加方法 StringPatter 用于在 Property 中 属性为 String 时 Pattern 将 List StringFomat 加载并显示为下拉框选择 代码如下 varfield grid columns Experimental get colNu

    2026年3月17日
    3
  • sql语句日期格式转换

    sql语句日期格式转换不多说直接放图筛选出每天每个人的成绩 selectuser sum score date format Xtime y m d asdatefromxg date 其中日期格式是采用 date format Xtime y m d 函数得到的结果

    2026年3月26日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号