还是继续以前的思路,作为C语言选手,必须掌握redis在c语言开发环境中的应用。
redis提供给c语言的软件包叫做hiredis,
“Hi~ o( ̄▽ ̄)ブ redis!”,这个名字起的甚合我意。
安装开发环境
yum install hiredis
yum install hiredis-devel
然后头文件路径为/usr/include/hiredis
库文件路径为/usr/lib64/libhiredis.so
代码部分
头文件包含
#include "hiredis/hiredis.h"
Makefile链接
LDFLAGS += -lhiredis
打开和关闭连接
redis连接和释放,我已经封装成函数,可以复制到你的代码中直接使用。
redisContext* redis_cn_init(void)
{
redisContext* con=NULL;
redisReply* pReply = NULL;
con= redisConnect(redis_server,redis_port);
if(NULL==con||con->err==1)
{
zlog_error(zlogc,"%s", con->errstr);
return NULL;
}
pReply = redisCommand(con, "auth password");
freeReplyObject(pReply);
return con;
}
int redis_cn_exit(redisContext* con)
{
redisFree(con);
return 0;
}
注意我在创建连接之后,就调用了一次auth password,这个是因为前一章我们配置了关于redis的验证密码,所以这里调用一次,完成了验证。
数据的读写
用的主要都是函数redisCommand,
/*
同步执行redis命令,和printf类似,%b传入二进制数据,要求有size_t参数指定长度。例如redisCommmand( c, "SET foo %b", arr, (size_t)len );
失败:返回NULL,并且err字段会置1,一旦执行出错,该redisContext就不能再使用,需要重新连接
成功:返回redisReply的指针
*/
void *redisCommand(redisContext *c, const char *format, ...);
其实还有一些组操作的redisCommandArgv,这里就不讲了,因为我也没用它
数据写入
数据写入以下面这个为例,cmd就是我们要执行的语句
int redis_write_ip(redisContext * rd_con,char* cmd)
{
redisReply* pReply = NULL;
pReply = redisCommand(rd_con, cmd);
freeReplyObject(pReply);
return 0;
}
一般我们不需要判断返回值,但是返回值的结构一定要接收,然后调用freeReplyObject释放掉,否则会有内存占用。----王老师
数据读取
最后就是比较复杂的数据读取了,因为返回值有多种情况,返回值的结构如下
typedef struct redisReply {
int type; //指明返回的类型
long long integer; /* 当type是REDIS_REPLY_INTEGER 的时候,它就是值*/
int len; /* Length of string */
char *str; /* 当type是REDIS_REPLY_ERROR 和REDIS_REPLY_STRING 的时候,它就是值*/
size_t elements; /* 当type是REDIS_REPLY_ARRAY 的时候,它就是element的个数*/
struct redisReply **element;/* 当type是REDIS_REPLY_ARRAY 的时候,它就是值*/
} redisReply;
type定义如下
#define REDIS_REPLY_STRING 1 //字符串
#define REDIS_REPLY_ARRAY 2 //数组,多个reply,通过element数组以及elements数组大小访问
#define REDIS_REPLY_INTEGER 3 //整型, integer字段
#define REDIS_REPLY_NIL 4 //空,没有数据
#define REDIS_REPLY_STATUS 5 //状态,str字符串以及len
#define REDIS_REPLY_ERROR 6 //错误,同STATUS
简单来说,就是根据type,去不同的地方拿值。
我一般通过在命令行做测试,然后再进行代码编写。反正数据类型是不会变化的,百试百灵
根据我的使用方法,简单列举了两种用法:
1.查询值是否在某个集合中,
这里用了集合(Set)的查询方法,判断某个IP在不在ALLIPS里面
在命令行中我们可以看到结果如下
127.0.0.1:6379> SISMEMBER ALLIPS 192.168.32.202
(integer) 1
可以发现返回值是一个整数,1表明在 0表明不在。
代码中的判断就这样的
int redis_is_ip_in(redisContext * rd_con,char* ip)
{
int res=nbl_no;
redisReply* pReply = NULL;
pReply = redisCommand(rd_con, "SISMEMBER ALLIPS %s",ip);
if(pReply->type==REDIS_REPLY_INTEGER)
{
if(pReply->integer == 1)
{
res=1;
}
}
freeReplyObject(pReply);
return res;
}
2.读取一个哈希值的全部内容,还是以前一张的流量统计为例,通过命令行
127.0.0.1:6379> HGETALL 192.168.32.202
1) "upload"
2) "51529"
3) "download"
4) "61284"
我们可以看出来返回值是数组,元素就在element中,然后每个element,都是字符串类型,所以c代码如下
int redis_getflow(redisContext * rd_con,char* ip,int* upload,int* download )
{
int res=0;
redisReply* pReply = NULL;
*upload = 0;
*download = 0;
pReply = redisCommand(rd_con, "HGETALL %s",ip);
if(pReply->type==REDIS_REPLY_NIL)
{
printf("ip:[%s] REDIS_REPLY_NIL",ip);
}
else if(pReply->type==REDIS_REPLY_ARRAY)
{
if(pReply->elements == 4)
{
*upload=atoi(pReply->element[1]->str);
*download=atoi(pReply->element[3]->str);
printf("full ip:[%s]:[%d],[%d]",ip,*upload,*download);
if((*upload)||(*download))
{
res=1;
}
}
else if(pReply->elements == 2)
{
if(strstr(pReply->element[0]->str,"upload"))
{
*upload=atoi(pReply->element[1]->str);
printf("upload ip:[%s]:[%d]",ip,*upload);
if(*upload)
{
res=1;
}
}
else if(strstr(pReply->element[0]->str,"download"))
{
*download=atoi(pReply->element[1]->str);
printf("download ip:[%s]:[%d]",ip,*download);
if(*download)
{
res=1;
}
}
}
}
else
{
printf("ip:[%s] [%d]",ip,pReply->type);
}
freeReplyObject(pReply);
return res;
}
代码可能看的不是很有条理,但是总结起来就是一句话:
根据命令行结果,调整c语言代码中的判断
经过一天的学习,基本就可以掌握redis在c语言中的应用。完成一些小的功能,还是足够的。有些东西要结合第一章来看
linux小知识–CentOS7安装配置开发Redis全过程(一)
好了,今天的砖就搬到这里了,全身心投入工作的话,八小时其实已然能够让你累的半死。昨天老板还问我为什么不加班,其实我不反对加班
但是想白嫖的话,那门也没有啊