Redis 拥有几乎所有主流编程语言的客户端(https://redis.io/clients),其中 C 语言的客户端推荐使用: hiredis 是一个轻量级的 C 语言编程客户端。它非常的简洁,仅仅提供了对 redis 通信协议的最小支持。同时它使用了一个高级别的 printf-like API,所以对于习惯了 printf 风格的 C 编程用户来说,其非常容易使用,而且 API 中没有明确的绑定每个 Redis 命令。 编译运行: 使用 hiredis 的 Synchronous API,需要掌握以下函数原型。 指针函数,输入 Redis Server 的 IP:Port,返回 redisContext 结构体类型指针。 redisContext 结构体用于保存连接状态,包含了一个 Int 类型的结构体成员 err。当 err 非空时,表示连接处于一个错误状态,此时可以通过查看 String 类型的 errstr 成员来获取错误信息。所以在调用 redisConnect() 后应该检查 redisContext 结构体的 err 成员来判断连接是否成功。 NOTE:redisContext 是线程非安全的,也就是说,多个线程同时访问一个 redisContext 很可能会出现问题。 空类型指针函数,具有可变长形参,输入 redisContext 结构体类型指针、Redis SQL 语句字符串。返回值为空类型指针,可以强制类型转换为任意类型,一般强制转换成为 redisReply 类型,然后对其进行后续处理,例如:查看执行结果或执行错误的结果。 redisCommand() 是一个 printf-like API,向 Redis Server 发送指令。 当 redisCommand() 调用失败时,返回为 NULL,同时设置 redisContext 结构体的 err 成员。一旦错误返回,redisContext 不能被重用,此时应该建立一个新的连接。 当 redisCommand() 成功调用时,返回的 redisReply 类型指针。 redisReply 结构体的 type 成员应该用于检查 Reply 类型,包括: 空类型函数,输入 redisCommand() 返回的 redisReply 指针变量,并释放 redisReply 指针变量所占用的内存。 在代码中应该使用 freeReplyObject() 来释放 Reply 占用的内存。注意,freeReplyObject() 会递归的释放数组中的资源,不需要手动释放数组资源。 空类型函数,输入 redisConnect() 返回的 conn 指针变量。该 API 会断开 Redis Server 的连接(关闭 Socket)并释放 redisContext 结构体所占用的内存。 同步调用简单,而异步调用的性能更高。hiredis 的 Asynchronous API 可以简易的与一些基于事件(Event)的函数库结合使用,例如 libev 和 ibevent。 redisAsyncConnect() 用于与 Redis Server 建立非阻塞连接,返回 redisAsyncContext 结构体类型指针,结构体的 err 成员用来检查连接的过程中是否发生了错误。注意,因为创建的是非阻塞的连接,所以 Kernel 并不会立马返回连接的结果。 同样,redisAsyncContext 也是线程非安全的。 在异步调用场景中,Redis 的操作命令被加入到事件循环队列,当命令执行完后再调用相应的回调函数来获得执行结果。回调函数的原型为: 以下是进行异步命令操作的函数: 与同步接口调用类似。执行成功返回 REDIS_OK,否则返回 REDIS_ERR。比如:在连接已经关闭的情况下再调用 redisAsyncCommand() 就会返回 REDIS_ERR。回调执行完毕后如果 reply 不为空,那么回调执行完毕后将自动对 reply 的资源进行回收。而当 Context 发生错误时,回调得到的 reply 则为空。 一个异步的连接可以通过下面这个函数终止: 当这个函数被调用时,异步连接并不会被立即关闭,而是等待所有与这个连接关联的异步命令操作执行完毕,并且回调事件已经执行完毕后才关闭此连接,这时在响应关闭连接事件的回调函数中得到的状态为 REDIS_OK,此连接的资源也将会被自动回收。 异步的 Context 可设置一个响应断开连接事件的回调函数,当连接断开时会相应执行。回调函数的原型为: 在断开连接的情况下,当连接是由用户自己断开的,那么 status 参数为 REDIS_OK。如果出现了其他错误,则 status 参数为 REDIS_ERR,此时可以通过 err 成员得到准确的错误码。 一个异步 Context 仅能设置一次断开连接的回调,如果再进行下一次设置将会返回 REDIS_ERR。设置断开连接回调函数的原型为: 当回调执行完毕后 Context 会自己释放资源。该回调事件给创建一个新连接提供了便利。 当 redisCommand 系列的 API 被调用时,hiredis 首先会根据 Redis 协议格式化该 API 传入的命令。然后将格式化的命令放入 redisContext 的输出缓冲区(output buffer)中。输出缓冲区是动态的,所以它可以容纳任意数量的命令。将命令放入输出缓冲区后,可以调用redisGetReply() 来获取执行命令的结果。redisGetReply() 有以下两种执行场景: 输入缓冲区(input buffer)为空: 输入缓冲区不为空: 对于序列化的命令,唯一需要做的事情就是将其填充到输出缓冲区。由于这个原因,hiredis 还可以使用 redisAppendCommand 来发送命令,并使用 redisGetReply 获取命令的单个回复。 redisGetReply() 返回值为 REDIS_OK 或 REDIS_ERR,是一个 int 类型。后者表示读取回复时出错,同样可以通过 err 成员获取到错误信息。 hiredis Pipelining 的使用方法如下: 该 APIs 还可以实现 Redis 的发布订阅机制(blocking subscriber): 当 hiredis 提供的 API(函数)调用不成功时,会返回 NULL 或 REDIS_ERR。此时 redisContext 结构体的 err 成员为非 0,并设置为以下常量之一: 以上错误,都可以通过 redisContext 结构体的 errstr 成员来查看错误信息。
目录
文章目录
Redis 客户端
HIREDIS
安装
$ git clone https://github.com/redis/hiredis.git $ cd hiredis $ make $ make install $ cp libhiredis.so /usr/lib64 /usr/lib $ /sbin/ldconfig
验证
#include <stdio.h> #include <hiredis/hiredis.h> int main() { redisContext *conn = redisConnect("127.0.0.1", 6379); if (conn == NULL || conn->err) { if (conn) { printf("Error: %sn", conn->errstr); } else { printf("Can't allocate redis contextn"); } } redisReply *reply = redisCommand(conn, "set foo 123"); freeReplyObject(reply); reply = redisCommand(conn, "get foo"); printf("foo: %sn", reply->str); freeReplyObject(reply); redisFree(conn); return 0; }
$ gcc test.c -o test -lhiredis $ ./test foo: 123
Synchronous API
redisConnect
redisContext *redisConnect(const char *ip, int port)
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;
redisCommand
void *redisCommand(redisContext *c, const char *format, ...);
reply = redisCommand(context, "SET foo bar");
reply = redisCommand(context, "SET foo %s", value);
reply = redisCommand(context, "SET %s %s", key, value);
reply = redisCommand(context, "SET foo %b", (size_t)valuelen);
argc = 3
。argv = {"set", "foo", "bar"}
。set foo bar
的 argvlen == {3, 3, 3}。如果 argvlen 为空,那么函数内部会自动调用 strlen() 求每个参数的长度。void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); // EXAMPLE: char hkey[] = "123456"; char hset[] = "hset"; char key[] = "testkey"; char hvalue[] = "3210"; int argc = 4; char *argv[] = {hset,key,hkey,hvalue}; size_t argvlen[] = {4,6,4,3}; redisCommandArgv(context,argc,argv,argvlen);
/* This is the reply object returned by redisCommand() */ 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;
redis->str
,字符串长度为 redis->len
。redis->elements
,数组值元素为 redis->element[i]
,每个元素都是一个 type==REDIS_REPLY_STRING 的 redisReply 结构体类型指针。元素的返回值可以通过 redis->element[i]->str
访问。reply->integer
。reply->str
,状态字符串长度为 reply->len
。比如:set foo bar
返回的状态为 OK,则 reply->str
为 “OK”。reply->str
当中。freeReplyObject
void freeReplyObject(void *reply);
redisFree
void redisFree(redisContext *c);
Asynchronous API
redisAsyncConnect
redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); if (c->err) { printf("Error: %sn", c->errstr); // handle error }
Sending commands and their callbacks
void(redisAsyncContext *c, void *reply, void *privdata);
int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...); int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen);
redisAsyncDisconnect
void redisAsyncDisconnect(redisAsyncContext *ac);
void(const redisAsyncContext *c, int status);
int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);
Pipelining
void redisAppendCommand(redisContext *c, const char *format, ...); void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
redisReply *reply; redisAppendCommand(context,"SET foo bar"); redisAppendCommand(context,"GET foo"); redisGetReply(context,(void *)&reply); // reply for SET freeReplyObject(reply); redisGetReply(context,(void *)&reply); // reply for GET freeReplyObject(reply);
reply = redisCommand(context, "SUBSCRIBE foo"); freeReplyObject(reply); while(redisGetReply(context, (void *)&reply) == REDIS_OK) { // consume message freeReplyObject(reply); }
Errors
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算