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 }
運行結果如下: