1.hiredis的介绍
hiredis是redis数据库一个轻量的C语言客户端库。
之所以轻量是由于它只是简单的提供了对redis操作语句支持的接口,并没有实现具体的操作语句的功能。但正是由于这种设计使我们只要熟悉了通用的redis操作语句就可以很容易的使用该库和redis数据库进行交互。
Hirides仅仅支持二进制安全的redis协议,所以你只能针对版本号大于等于1.2.0的redis服务端使用。
库包含多种API,包括同步命令操作API、异步命令操作API和对应答数据进行解析的API。
2.主要结构体和编程
1)连接redis服务器
redisContext *redisConnect(const char *ip, int port);
/* Context for a connection to Redis */
typedef struct redisContext {
int err; /* Error flags, 0 when there is no error */
char errstr[128]; /* String representation of error when applicable */
int fd;
int flags;
char *obuf; /* Write buffer */
redisReader *reader; /* Protocol reader */
enum redisConnectionType connection_type;
struct timeval *timeout;
struct {
char *host;
char *source_addr;
int port;
} tcp;
struct {
char *path;
} unix_sock;
} redisContext;
redisConnect函数用来创建一个redisContext,redisContext的结构体如上。由结构体redisContext可知,其包含了hiredis连接服务器状态的相关信息。
实例代码:
redisContext *redisconn = redisConnect("127.0.0.1", 6379);
if (redisconn != NULL && redisconn->err)
{
printf("Error: %s\n", redisconn->errstr);
}
2)发送redis指令
void *redisCommand(redisContext *c, const char *format, ...)
typedef struct redisReply {
int type; /* REDIS_REPLY_* */
long long integer; /* The integer when type is REDIS_REPLY_INTEGER */
size_t len; /* Length of string */
char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */
size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */
struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */
} redisReply;
当命令被成功执行后redisCommand会有相应的返回值用结构体redisReply来表示,可以通过redisReply来查看指令执行的情况。例如redisReply中的type就是执行成功与否的返回状态。type的取值有下面几种:
/*返回字符串标识。可以通过reply->str得到具体值,通过reply->len得到信息长度。*/
#define REDIS_REPLY_STRING 1
/*返回数据集标识。数据集中元素的数目可以通过reply->elements获得,每个元素是个redisReply对象,元素值可以通过reply->element[..index..].*形式获得,用在获取多个数据结果的操作。*/
#define REDIS_REPLY_ARRAY 2
/*返回整型标识。可以通过reply->integer变量得到类型为long long的值。*/
#define REDIS_REPLY_INTEGER 3
/*返回nil对象,说明不存在要访问的数据。*/
#define REDIS_REPLY_NIL 4
/*返回执行结果为状态的命令。比如set命令的返回值的类型是REDIS_REPLY_STATUS,然后只有当返回信息是"OK"时,才表示该命令执行成功。可以通过reply->str得到文字信息,通过reply->len得到信息长度。*/
#define REDIS_REPLY_STATUS 5
/*返回错误。错误信息可以通过reply->str得到文字信息,通过reply->len得到信息长度。*/
#define REDIS_REPLY_ERROR 6
此外,可以观察到redis的指令函数接口很想c库函数printf();看看redisCommand函数的实现源码:
void *redisCommand(redisContext *c, const char *format, ...) {
va_list ap;
void *reply = NULL;
va_start(ap,format);
reply = redisvCommand(c,format,ap);
va_end(ap);
return reply;
}
和系统函数printf如出一辙,可知两者的用法大相径庭。
执行完命令调用后应该通过freeReplyObject()释放redisReply。
实例代码1:
redisReply *reply1 = (redisReply*)redisCommand(conn, "set KEY VALUE");
printf("type:%d\n", reply1->type);
printf("reply->str:%s\n", reply1->str);
printf("reply->len:%d\n", reply1->len);
freeReplyObject(reply1);
执行的结果:
type:5
reply->str:OK
reply->len:2
可见该代码向redis数据库增加一个key-value对成功。
实例代码2:
redisReply *reply2 = (redisReply*)redisCommand(conn, "keys *");
size_t size = reply2->elements;
int i;
for(i = 0; i < size; i++)
{
printf("%s\n", reply2->element[i]->str);
}
freeReplyObject(reply2);
执行的结果:
KEY
name
可见代码向redis数据库获取数据集合成功,并返回了所有的key。
示例代码3:
char id[10] = "studentid";
char sno[10] = "123456";
redisReply *reply3 = (redisReply*)redisCommand(conn, "set %s %s", id, sno);
freeReplyObject(reply3);
发送多条redis命令函数:
void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen)
3)释放资源
void redisFree(redisContext *c)
此函数立马关闭socket并且释放创建context时分配的资源。