linux c 封装redis,封装hiredis——C++与redis对接(一)(string的SET与GET操作)
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操作)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql无法启动修复_记一次MySQL
- 下一篇: weblogic 10.3.0.0 fo