封装hiredis——C++与redis对接(⼀)(string的SET与GET操
作)
  在菜鸟教程⾃学了redis,总想着像Mysql⼀样,在C/C++中进⾏对接。于是查询了⼀些资料,最后到了hiredis。然⽽直接⽤它的话,难免有点不⽅便。于是,对其进⾏封装。
  下载好之后,由于其⾃带Makefile,只要make⼀下就编译出静态库与动态库了,接着把头⽂件和静/动态库放在相应的⽂件夹⾥就可以了。注意如果使⽤动态库,⽽且是放在/usr/local/lib/⾥,得执⾏ldconfig命令,来更新⼀下配置,或者得配置⼀下动态库路径。
  安装好了就是如何使⽤的事了。
  学习hiredis主要是参考这两个链接:
  ⼀共就五个函数。
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 *)
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 <string>
4namespace ccx{
5using std::string;
6class RedisConf
7 {
8public:
9        RedisConf();
redhat和ubuntu的区别10void getConf();
11string getIP();
12int getPort();
13private:
14string _ip;
15int _port;
16 };
17 }
18#endif
<
1 #include "redisConf.h"
2 #include <stdlib.h>
3 #include <json/json.h>
4 #include <string>
5 #include <iostream>
6 #include <fstream>
7
8namespace ccx{
9
10using std::ifstream;
11using std::cout;
12using std::endl;
13
14 RedisConf::RedisConf()
15 {
16    getConf();
17 }
18
19void RedisConf::getConf()
20 {
21    ifstream ifs;
22    ifs.open("redisConf.json");
23if(!d())
24    {
25        cout << "open RedisConf.json error" << endl;
26        exit(EXIT_FAILURE);
27    }
28
29    Json::Value root;
30    Json::Reader reader;
31if(!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
42string RedisConf::getIP()
43 {
44return _ip;
45 }
46
织梦蓝雪47int RedisConf::getPort()
48 {
49return _port;
50 }
51
52 }
  然后是⽬前的redis类:
redis.h
1 #ifndef __REDIS_H__
2#define __REDIS_H__
3
4 #include "redisConf.h"
5
6 #include <hiredis/hiredis.h>
7
8
9namespace ccx{
10
11class Redis
12 {
13public:
14        Redis();
15public:
16void Connect();
17void disConnect();
18public:
19void setString(const string & key, const string & value); 20void setString(const string & key, const int & value); 21void setString(const string & key, const float & value); 22private:
23void setString(const string & data);
24public:
25void getString(const string & key, string & value);
26void getString(const string & key, int & value);
27void getString(const string & key, float & value);
28private:
29void getString(const string & key);
30private:
31void freeReply();
32bool isError();
33private:
34        RedisConf _conf;
35        redisContext * _context;
36        redisReply * _reply;
37 };
38 }
39
40#endif
  下⾯结合写好的代码说说前⾯的五个函数。
  函数1是⽤来连接redis的,具体如下:
1void Redis::Connect()
2 {
3    _context = ::redisConnect(_IP().c_str(), _Port());
4    cout << _IP() << "-" << _Port() << endl;
5if(_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了,要断开连接时使⽤的:
1void 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");
  可以这样⽤:
1char * command = "SET name lili";
2 reply = (redisReply*)::redisCommand(context, command);
java代码中设置埋点3char * s1 = "name";
4char * 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 的返回结果的:
1void Redis::freeReply()
2 {
3if(_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;\
4string s;\
5    getline(ss, s);\
6    setString(s);
1void Redis::setString(const string & key, const string & value)
2 {
3    SETSTRING(key, value);
4 }
5void Redis::setString(const string & key, const int & value)
6 {
7    SETSTRING(key, value);
8 }
9void Redis::setString(const string & key, const float & value)
10 {
11    SETSTRING(key, value);
12 }mysql安装教程菜鸟课程
  使⽤C++中的stringstream,会⽐⽤“%d”、“%s”、“%f”来区分类型少些代码。两种⽅法的结果是相同的。
  它们共⽤的setString⽅法:
1void Redis::setString(const string & data)
2 {
3    freeReply();
4    _reply = (redisReply*)::redisCommand(_context, data.c_str());
5if(!isError())
6    {
7if (!(_reply->type == REDIS_REPLY_STATUS && strcasecmp(_reply->str,"OK") == 0))
8        {
9            cout << "Failed to execute SET(string)" << endl;
10        }
11    }
12 }
  这⾥的isError是⽤来判断是否连接异常的:
1bool Redis::isError()
2 {
3if(NULL == _reply)
4    {
5        freeReply();
6        disConnect();
7        Connect();
8return true;
9    }
10return false;
11 }
  如果连接异常,得断开重连。
  在redis命令⾏⾥,如果set成功,会提⽰“OK”。于是,这⾥先判断了⼀下命令结果的数据类型,如果是字符串,再判断它是不是“OK”,以此来判断set是否成功。
  对于get,我试了各种⽅法,都⽆法直接从命令结果中提取出数字,暂时还没到原因。但是数字却可以以字符串格式得到。于是,使⽤了atoi来处理:
1void Redis::getString(const string & key)
2 {
3    freeReply();
4    _reply = (redisReply*)::redisCommand(_context, "GET %s", key.c_str());
5 }
6
7void Redis::getString(const string & key, string & value)
8 {
9    getString(key);
10if(!isError() && _reply->type == REDIS_REPLY_STRING)
11    {
12        value = _reply->str;
13    }
14 }
15
16void Redis::getString(const string & key, int & value)
17 {
18    getString(key);
19if(!isError() && _reply->type == REDIS_REPLY_STRING)
20    {
21        value = ::atoi(_reply->str);
22    }
23 }
24
25void Redis::getString(const string & key, float & value)
26 {
27    getString(key);
28if(!isError() && _reply->type == REDIS_REPLY_STRING)
29    {
30        value = ::atof(_reply->str);
31    }
32 }
<
1 #include "redis.h"
2
3 #include <string.h>
4 #include <stdlib.h>
5
6 #include <sstream>
7 #include <iostream>
8
9namespace ccx{
10
11using std::cout;
12using std::endl;
13using std::stringstream;
14
15#define SETSTRING(key, value) \
16    stringstream ss;\
17    ss << "SET " << key << "" << value;\
18string s;\
19    getline(ss, s);\
20    setString(s);
21
22 Redis::Redis()
23 : _conf()
24 {
25 }
26
27void Redis::Connect()
28 {
29    _context = ::redisConnect(_IP().c_str(), _Port());
30    cout << _IP() << "-" << _Port() << endl;
31if(_context && _context->err)
32    {
33        cout << "connect redis error" << endl;
34        exit(EXIT_FAILURE);
35    }
36    cout << "redis Connect success" << endl;
37 }
38
39void Redis::disConnect()
40 {
沈青鸾风璃宸神医弃妃免费阅读41    ::redisFree(_context);
42    cout << "redis disConnect success" << endl;
43 }
44
45void Redis::setString(const string & data)
46 {
47    freeReply();
48    _reply = (redisReply*)::redisCommand(_context, data.c_str());
49if(!isError())
50    {
51if (!(_reply->type == REDIS_REPLY_STATUS && strcasecmp(_reply->str,"OK") == 0))
52        {
53            cout << "Failed to execute SET(string)" << endl;
54        }
55    }
56 }
57
58void Redis::setString(const string & key, const string & value)
59 {
60    SETSTRING(key, value);
61 }
62
63void Redis::setString(const string & key, const int & value)
64 {

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。