上文提到 搭建完成後 咱們選擇客戶端的開源庫進行鏈接 有如下三種選擇 html
1 acl-redis 緣由是支持VC 國產 做者博客 acl 框架庫簡介 用 acl 庫編寫高效的 C++ redis 客戶端應用ios
代碼支持VC編譯 最好使用vc2008-vc2012編譯,這樣工程包含redis的示例。 我選擇的是vc2017的工程圖標打開工程的,因此沒有示例c++
做者有中文博客 對該庫有詳細的介紹 還有QQ羣能夠進行討論 技術支持比較強大。git
可是問題在於 整個工程偏向C風格 竟然是用本身的thread和string。github
C++工程若選擇該庫,在使用何種風格和多線程字符串等使用方式上會收到必定的約束redis
2 也能夠選擇 上面提到的redis工程中已經封裝好的hredis 可參考個人這篇文章 windows下使用redis c++ 。windows
這個庫是redis工程中就包含的 原版匹配,本來是最佳選擇。做爲本系列演示操做多線程
3 cpp_redis 地址 https://github.com/cylix/cpp_redis + https://github.com/Cylix/tacopie/tree/8714fcec4ba9694fb00e83e788aadc099bd0fd5d 框架
這個感受是最適合開始使用的庫了 c++11 輕量級 跨平臺的 redis客戶端ide
不過穩定性和效率還須要再行觀察
選定庫後 來個簡短的例子 測試下。 代碼我稍微封裝了下 使用了模板,在輸入不一樣的類型時候根據模板自動匹配到相應的類型操做函數上
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 }
運行效果圖:(記得開啓redis)