基于acl封装c\c++ redis客户端(redis-client客户端 代码实现)

详述
基于acl框架库封装redis_c++客户端
(仅供内部使用)

目录

1 案例描述 1
2 案例分析 1
2.1 acl框架库描述 1
2.2 acl框架库结构分析 1
3 解决过程 2
3.1 新建动态/静态库工程 2
3.2 引入库和头文件 3
3.3 具体redis功能实现 3
3.3.1 初始化 3
3.3.2 API定义、使用 4
3.3.3 Redis客户端脚本支持 4
解决结果 5
4 总结 5

关键词:
RedisClient_C、acl框架库、c++、redis客户端、redis服务器、redis集群、redis从服务器
摘 要:
主要讲述如何利用开源acl框架库,编写一个基于c++的redis客户端动态库(RedisClient_C);业务程序可以直接利用该RedisClient_C库和redis服务器交互(添加、删除、处理数据);

案例分析

acl框架库描述

acl网络通信与服务器编程框架是一个开源C/C++库;开源代码下载地址:
svn://svn.code.sf.net/p/acl/code/trunk
acl库中有丰富的网络通信功能模块,虽然该模块是对底层系统API的封装,却提供了丰富的高级功能,同时屏蔽了在使用底层系统API容易出错的地方,可以方便程序员快速开发出高效、稳定、安全的网络通信应用;
其中redis客户端和服务器通信模型是acl库中的一种,本文也是利用该模型代码库、头文件实现的客户端封装;该库也是redis官网公布的c++客户端方案的一种;

acl框架库结构分析

封装前我们要先了解开源代码结构,分析寻找要利用的开源代码;框架库中代码结构分为:

  • lib_acl: 该库是最基础的库,其它 4 个库均依赖于该库; 该库以 C 语言实现。
  • lib_protocol: 该库主要实现了 http 协议及 icmp/ping 协议; 该库以 C 语言实现。
  • lib_acl_cpp: 该库用 C++ 语言封装了 lib_acl/lib_protocol 两个库,同时增加了一些其它有价值的功能应用。
  • lib_dict: 该库主要实现了 KEY-VALUE 的字典式存储库,该库另外还依赖于 BDB, CDB 以及 tokyocabinet 库。
  • lib_tls: 该库封装了 openssl 库,使 lib_acl 的通信模式可以支持 ssl。
    五工程中,我们只需要关注lib_acl和lib_acl_cpp两个库工程,这两个库已经实现了redis服务器C/S通信的全部功能,其他部分有兴趣可以自己研究;

解决过程

了解过acl框架库后,就要用它来封装实现c++版本的reids客户端,客户端用vs2010来建立工程,具体实现细节如下:

新建动态/静态库工程

新建库工程,客户端具体要以动态还是静态形式来生成,可以自行选择;其他主要是添加导入、导出函数控制,本文直接封装为客户端类,对类做导入、导出控制更方便;
需要注意的是工程中需要定义个嵌套类,用作存储有些不需要对外暴漏的对象、成员;

// 通过宏来控制是导入还是导出
#ifdef DLL_EXPORT
#define DLL_SAMPLE_API __declspec(dllexport)
#else
#define DLL_SAMPLE_API __declspec(dllimport)
#endif
class DLL_SAMPLE_API cRedisCli
    {
    public:
        //必须以具体参数来初始化,初始化过程直接和redis-server建链
        cRedisCli(char* pAddr, char* pPort, int conn_timeout=10,int rw_timeout=10);
        virtual ~cRedisCli(){}
        ……对外暴漏接口区
    private:
        class cRedisPrivate; // 嵌套类,定义放在cpp
        cRedisPrivate* m_pcPrivate; // 用以存储redis初始化操作对象,不对外暴漏
}

引入库和头文件

工程首先要包含lib_acl_vc2010d.lib和lib_acl_cpp_vc2010d.lib两个库,两个库通过acl下载代码自行编译即可获得,路径分别为acl\lib_acl、acl\lib_acl_cpp;
两个库依赖的头文件是acl_cpp/lib_acl.hpp和lib_acl.h:

  • acl_cpp/lib_acl.hpp文件中主要间接包含了通信之外的附加功能头文件定义,包括所有的redis通信需要的头文件定义,例如针对调用connect、key、hash、list、string等功能需要的类、结构体封装定义,各个功能下的API接口类封装定义;
  • lib_acl.h主要包含的是acl库的基础定义,客户端对该头文件使用不多。

具体redis功能实现

初始化

首先要实现的就是和服务器建链,即调用RedisClient_C客户端库时,需要传入构造函数cRedisCli()必须的地址、端口参数,构造函数内部用参数初始化一个局部静态redis_client对象;
redis_client再作为cRedisPrivat私有嵌套类的构造参数new一个私有类对象,私有嵌套类cRedisPrivate的构造函数中采用初始化列表,对我们要用到的redis命令API封装类对象进行实例化;
特别注意,redis_client对象必须定义为static静态对象,该对象是作为指针传入各个redis命令实例类的,程序运行全程都需要其有效。

cRedisCli::cRedisCli(char* pAddr, char* pPort, int conn_timeout/*=10*/,int rw_timeout/*=10*/)
{
    acl::string addr(pAddr + pPort);
    bool slice_req = false;
    acl::acl_cpp_init();
    static acl::redis_client client(addr.c_str(), conn_timeout, rw_timeout);
    client.set_slice_request(slice_req);
    m_pcPrivate = new cRedisPrivate(&client);
    if (m_pcPrivate == NULL)
        printf("[cRedisCli] New cRedisPrivate failed !\n");
}

// 嵌套类
class cRedisCli::cRedisPrivate
{
    friend class cRedisCli;
public:
    cRedisPrivate(acl::redis_client* pclient):m_RedisCon(pclient),m_RedisSer(pclient),m_RedisHash(pclient),m_RedisKey(pclient),m_RedisScript(pclient),m_RedisSet(pclient)
    {
    }

private:
    acl::redis_connection m_RedisCon;
    acl::redis_key  m_RedisKey;
    acl::redis_server m_RedisSer;
    acl::redis_hash m_RedisHash;
    acl::redis_script m_RedisScript;
    acl::redis_set m_RedisSet;
};

API定义、使用

初始化之后就是针对RedisClient_C客户端库想暴漏的API进行封装即可,简单举例一个,Redis客户端支持向服务器设置客户端名称,对该功能API封装实现如下:

bool cRedisCli::SetClientName(char* pName)
{
    if (!pName || !m_pcPrivate)
        return false;
    acl::string buf(pName);
    m_pcPrivate->m_RedisSer.clear();
    if (m_pcPrivate->m_RedisSer.client_setname(buf.c_str()) == false)
        return false;
    printf("ClientSetName ok\r\n");
    return true;
}

Redis客户端脚本支持

Acl框架库提供的Redis客户端API中无疑不会放过lua脚本这个大功能,针对脚本acl专门提供了一个操作封装类acl::redis_script,客户端执行函数为acl::redis_script:eval();
需要特别描述的是eval函数执行脚本后的返回值为redis_result对象指针,返回内容分为五类,对于普通的字符串返回,该方法比较简单实用,但对于lua脚本中比较复杂的table对象(即c++中的结构体),redis_result对象返回后提取相对比较麻烦,比较有效的解决方法是使用lua脚本的xml处理功能直接转换为xml字符串再返回,上层业务能够简单明了的拿到一个层级分明的table;
解决结果

你可能感兴趣的:(redis,redis,acl,redis-client,redis,c++)