• redis在游戏服务器中的使用初探(二) 客户端开源库选择


    上文提到 搭建完成后 我们选择客户端的开源库进行连接 有以下三种选择 

    1 acl-redis 原因是支持VC 国产  作者博客   acl 框架库简介  用 acl 库编写高效的 C++ redis 客户端应用

    代码支持VC编译 最好使用vc2008-vc2012编译,这样工程包含redis的示例。 我选择的是vc2017的工程图标打开工程的,所以没有示例

    作者有中文博客 对该库有详细的介绍 还有QQ群可以进行讨论 技术支持比较强大。

    但是问题在于 整个工程偏向C风格 居然是用自己的thread和string。

    C++工程若选择该库,在使用何种风格和多线程字符串等使用方式上会收到一定的约束

    2 也可以选择 上面提到的redis工程中已经封装好的hredis 可参考我的这篇文章   windows下使用redis c++    。

    这个库是redis工程中就包含的 原版匹配,原本是最佳选择。作为本系列演示操作

     

    3 cpp_redis    地址 https://github.com/cylix/cpp_redis + https://github.com/Cylix/tacopie/tree/8714fcec4ba9694fb00e83e788aadc099bd0fd5d 

     这个感觉是最适合开始使用的库了 c++11 轻量级 跨平台的 redis客户端

    不过稳定性和效率还需要再行观察

    选定库后 来个简短的例子 测试下。 代码我稍微封装了下 使用了模板,在输入不同的类型时候根据模板自动匹配到相应的类型操作函数上

      1 // myRedisCli.cpp: 定义控制台应用程序的入口点。
      2 //
      3 
      4 #include "stdafx.h"
      5 #include <assert.h>
      6 #include <winsock2.h>
      7 #include <string.h>
      8 #include <tuple>
      9 #include <iostream>
     10 #include <sstream>
     11 #include <string.h>
     12 #include"hiredis/hiredis.h"
     13 
     14 
     15 class RedisConnect {
     16 public:
     17     RedisConnect() :redisCon(nullptr), reply(nullptr) {}
     18 
     19     bool Init(const std::string& ip, int port) {
     20         if (nullptr != redisCon) {
     21             return false;
     22         }
     23         redisCon = redisConnect(ip.c_str(), port);
     24         if (redisCon->err) {
     25             std::cerr << "error code : " << redisCon->err << ". " << redisCon->errstr << std::endl;
     26             return false;
     27         }
     28 
     29         return true;
     30     }
     31     void freeReply()
     32     {
     33         if (nullptr != reply)
     34         {
     35             ::freeReplyObject(reply);
     36             reply = nullptr;
     37         }
     38     }
     39 
     40     template<class T>
     41     bool GetVal(const std::string& key, T& value) {
     42         return Get(key, value);
     43     }
     44 
     45     template<class T, class... Args>
     46     bool HashSet(const std::string command, T head, Args... rest) {
     47         std::stringstream ss;
     48         ss << command << " " << head << " ";
     49         return HashSetInner(ss, rest...);
     50     }
     51 
     52     template<typename T>
     53     bool Set(const std::string & key, const T& value)
     54     {
     55         bool bret = false;
     56         std::stringstream ss;
     57         ss << "SET " << key << " " << value;
     58         std::string s;
     59         getline(ss, s);
     60         return Set(s);
     61     }
     62 
     63 
     64     bool InitWithTimeout(const std::string& ip, int port, int seconds) {
     65         if (nullptr != redisCon) {
     66             return false;
     67         }
     68         struct timeval tv;
     69         tv.tv_sec = seconds;
     70         tv.tv_usec = 0;
     71         redisCon = redisConnectWithTimeout(ip.c_str(), port, tv);
     72         if (redisCon->err) {
     73             std::cerr << "error code : " << redisCon->err << ". " << redisCon->errstr << std::endl;
     74             return false;
     75         }
     76         return true;
     77     }
     78 
     79     ~RedisConnect() {
     80         freeReply();
     81         if (nullptr == redisCon) {
     82             redisFree(redisCon);
     83             redisCon = nullptr;
     84         }
     85     }
     86 private:
     87     void GetString(const std::string & key)
     88     {
     89         freeReply();
     90         reply = (redisReply*)::redisCommand(redisCon, "GET %s", key.c_str());
     91     }
     92 
     93     bool Get(const std::string& key, std::string & value) {
     94         bool bret = false;
     95         GetString(key);
     96         if (nullptr == reply) {
     97             std::cout << "Failed to execute " << __FUNCTION__ << std::endl << std::endl;
     98             return bret;
     99         }
    100         else if (reply->type == REDIS_REPLY_NIL) {
    101             std::cout << __FUNCTION__ << ". Key = "" << key << "" find nothing" << std::endl << std::endl;
    102             return bret;
    103         }else if( reply->type != REDIS_REPLY_STRING) {
    104             std::cout << "Failed to execute " << __FUNCTION__ << std::endl << std::endl;
    105             return bret;
    106         }
    107         value = reply->str;
    108         bret = true;
    109         return bret;
    110     }
    111 
    112     bool Get(const std::string& key, int & value) {
    113         bool bret = false;
    114         GetString(key);
    115         if (nullptr == reply) {
    116             std::cout << "Failed to execute " << __FUNCTION__ << std::endl << std::endl;
    117             return bret;
    118         }
    119         else if (reply->type == REDIS_REPLY_NIL) {
    120             std::cout << __FUNCTION__ << ". Key = "" << key << "" find nothing" << std::endl << std::endl;
    121             return bret;
    122         }
    123         else if (reply->type != REDIS_REPLY_STRING) {
    124             std::cout << "Failed to execute " << __FUNCTION__ << std::endl << std::endl;
    125             return bret;
    126         }
    127         value = ::atoi(reply->str);
    128         bret = true;
    129         return bret;
    130     }
    131 
    132     bool Get(const std::string& key, float & value) {
    133         bool bret = false;
    134         GetString(key);
    135         if (nullptr == reply) {
    136             std::cout << "Failed to execute " << __FUNCTION__ << std::endl << std::endl;
    137             return bret;
    138         }
    139         else if (reply->type == REDIS_REPLY_NIL) {
    140             std::cout << __FUNCTION__ << ". Key = "" << key << "" find nothing" << std::endl << std::endl;
    141             return bret;
    142         }
    143         else if (reply->type != REDIS_REPLY_STRING) {
    144             std::cout << "Failed to execute " << __FUNCTION__ << std::endl << std::endl;
    145             return bret;
    146         }
    147         value = ::atof(reply->str);
    148         bret = true;
    149         return bret;
    150     }
    151 
    152     bool HashSetInner(std::stringstream& ss)
    153     {
    154         std::string data;
    155         getline(ss, data);
    156         //std::cout << __FUNCTION__ << " " << data << std::endl;
    157         bool bret = false;
    158         freeReply();
    159         reply = (redisReply*)::redisCommand(redisCon, data.c_str());
    160 
    161         if (reply->type == REDIS_REPLY_ERROR ||
    162             (reply->type == REDIS_REPLY_STATUS && _stricmp(reply->str, "OK") != 0))
    163         {
    164             if (reply->str != nullptr) {
    165                 std::cout << reply->str << std::endl;
    166             }
    167             std::cout << "Failed to execute " << __FUNCTION__ << std::endl << std::endl;
    168             return bret;
    169         }
    170 
    171         bret = true;
    172 
    173         return bret;
    174     }
    175 
    176     template<class T, class... Args>
    177     bool HashSetInner(std::stringstream& ss, T head, Args... rest)
    178     {
    179         ss << head << " ";
    180         return HashSetInner(ss, rest...);
    181     }
    182 
    183     bool Set(std::string data)
    184     {
    185         bool bret = false;
    186         freeReply();
    187         reply = (redisReply*)::redisCommand(redisCon, data.c_str());
    188 
    189         if (!(reply->type == REDIS_REPLY_STATUS && _stricmp(reply->str, "OK") == 0))
    190         {
    191             std::cout << reply->str << std::endl;
    192             std::cout << "Failed to execute " << __FUNCTION__ << std::endl;
    193             return bret;
    194         }
    195         bret = true;
    196         return bret;
    197     }
    198 
    199     redisContext* redisCon;
    200     redisReply * reply;
    201 };
    202 
    203 
    204 
    205 
    206 int main()
    207 {
    208     RedisConnect r;
    209 
    210     bool b = r.InitWithTimeout("127.0.0.1", 6379, 5);
    211     if (!b)
    212         return -1;
    213 
    214     r.Set("testtimes", 1);
    215     r.Set("float:pi", 3.14159265);
    216     r.Set("string", "test");
    217     std::string retStr;
    218     r.GetVal("string", retStr);
    219     float f;
    220     r.GetVal("float:pi", f);
    221     int i;
    222     r.GetVal("testtimes", i);
    223 
    224     r.GetVal("wqe42", retStr);
    225 
    226     r.HashSet("hset", "myhash", "field1", 123.2342343);
    227     r.HashSet("hmset", "myhash", "field1", 1111, "field2", "f2");
    228     
    229 
    230 
    231     r.HashSet("hset", "myhash", "field1", 123.2342343);
    232     r.HashSet("hmset", "myhash", "field1", 1111, "field2", "f2");
    233 
    234     //wrong command
    235     //r.HashSet("hset", "myhash", "field1", 1, 123.2342343);
    236     //r.HashSet("hmset", "myhash", "field1", 1, 1111, "field2", "f2");
    237 
    238     std::cout << "finish !" << std::endl;
    239     return 0;
    240 }
    MyHredisCli

    运行效果图:(记得开启redis)

    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    ARC109 题解&总结 ABCDEF
    List、Set、Map的学习
    数据结构和算法-栈
    spring-常见知识点(一)
    spring-AOP实现原理(二)
    spring-AOP实现原理(一)
    MVCC详解
    MVCC能否解决幻读
    ArrayList和LinkedList的区别
    架构设计-秒杀架构设计
  • 原文地址:https://www.cnblogs.com/itdef/p/9554676.html
Copyright © 2020-2023  润新知