0. 前言
Hiredis是一個Redis的C用戶端庫函數,基本實作了Redis的協定的最小集。這裡對hiredis的api作基本的介紹以及應用,主要參考hiredis的README檔案以及相關源碼。
1. 同步API
redisContext,該庫的上下文環境。
1 /* Context for a connection to Redis */
2 typedef struct redisContext {
3 int err; /* Error flags, 0 when there is no error */
4 char errstr[128]; /* String representation of error when applicable */
5 int fd;
6 int flags;
7 char *obuf; /* Write buffer */
8 redisReader *reader; /* Protocol reader */
9
10 enum redisConnectionType connection_type;
11 struct timeval *timeout;
12
13 struct {
14 char *host;
15 char *source_addr;
16 int port;
17 } tcp;
18
19 struct {
20 char *path;
21 } unix_sock;
22
23 } redisContext;
a. 連接配接Redis
1 //連接配接redis,若出錯redisContext.err會設定為1,redisContext.errstr會包含描述錯誤資訊
2 redisContext *redisConnect(const char *ip, int port);
b. 同步執行Redis指令
1 /*
2
3 同步執行redis指令,和printf類似,%b傳入二進制資料,要求有size_t參數指定長度。例如redisCommmand( c, "SET foo %b", arr, (size_t)len );
4 失敗:傳回NULL,并且err字段會置1,一旦執行出錯,該redisContext就不能再使用,需要重新連接配接
5 成功:傳回redisReply的指針
6
7 */
8 void *redisCommand(redisContext *c, const char *format, ...);
1 /*
2 發送一組指令,通過argv以及argvlen指定,當argvlen為NULL時,argv每個字元串的長度通過strlen來計算,是以當需要傳輸二進制資料時,整個argvlen資料都要輸入。
3 */
4 void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
5
6 /*
7 Piplining,追加的指令後可以通過redisGetReply來擷取指令的傳回值。
8 */
9 void redisAppendCommand(redisContext *c, const char *format, ...);
10 void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
11
12 //擷取指令傳回值,注:使用freeReplyObject釋放
13 int redisGetReply(redisContext *c, void **reply);
c. 響應的資料結構
typedef struct redisReply {
int type; /* REDIS_REPLY_* */ //指明傳回的類型
long long integer; /* The integer when type is REDIS_REPLY_INTEGER */
int 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傳回資料的類型,redisReply.type字段
1 #define REDIS_REPLY_STRING 1 //字元串
2 #define REDIS_REPLY_ARRAY 2 //數組,多個reply,通過element數組以及elements數組大小通路
3 #define REDIS_REPLY_INTEGER 3 //整型, integer字段
4 #define REDIS_REPLY_NIL 4 //空,沒有資料
5 #define REDIS_REPLY_STATUS 5 //狀态,str字元串以及len
6 #define REDIS_REPLY_ERROR 6 //錯誤,同STATUS
d. 釋放資源
1 //釋放reply結構
2 void freeReplyObject(void *reply);
//關閉連接配接并釋放記憶體
void redisFree(redisContext *c);
e. 錯誤字段說明 redisContext.err
1 //錯誤字段,會設定為以下其中一個值
2 #define REDIS_ERR_IO 1 /* Error in read or write */
3 #define REDIS_ERR_EOF 3 /* End of file */
4 #define REDIS_ERR_PROTOCOL 4 /* Protocol error */
5 #define REDIS_ERR_OOM 5 /* Out of memory */
6 #define REDIS_ERR_OTHER 2 /* Everything else... */
2. 異步API
待補充
3. 同步API示例(實作訂閱功能)
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "hiredis.h"
4
5 void ProcessReply( redisReply * pReply )
6 {
7 redisReply * pSubReply = NULL;
8
9 if ( pReply != NULL && pReply->elements == 3 )
10 {
11 pSubReply = pReply->element[2];
12 printf( "Msg [%s]\n", pSubReply->str );
13 }
14 }
15
16 int main( int argc, char const *argv[] )
17 {
18 redisContext * pContext = redisConnect( "127.0.0.1", 6379 );
19
20 if ( NULL == pContext || pContext->err == 1 )
21 {
22 printf( "%s\n", pContext->errstr );
23 exit( -1 );
24 }
25
26 char * pKey = "DATABUS:REQ";
27
28 redisReply * pReply = redisCommand( pContext, "SUBSCRIBE %s", pKey );
29 freeReplyObject( pReply );
30 while ( redisGetReply( pContext, (void **)&pReply ) == REDIS_OK )
31 {
32 ProcessReply( pReply );
33 freeReplyObject( pReply );
34 }
35
36 redisFree( pContext );
37
38 return 0;
39 }