程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++ Redis mset 二進制數據接口封裝方案

C++ Redis mset 二進制數據接口封裝方案

編輯:關於C++
內容目錄:   需求 簡單拼接方案 redisCommandArgv接口傳遞 方案 redisCommandArgv接口傳遞的Vector方案 二進制校驗 參考資料 C++ Redis mset 二進制數據接口封裝方案   需求   C++中使用hiredis客戶端接口訪問redis;  需要使用mset一次設置多個二進制數據   以下給出三種封裝實現方案;   簡單拼接方案   在redis-cli中,mset的語法是這樣的:   /opt/colin$./redis-cli mset a 11 b 22 c 333 OK 按照這樣的語法拼接後,直接使用hiredis字符串接口redisCommand傳遞:   void msetNotBinary(redisContext *c, const vector<string> &vtKey, const vector<string> & vtVal ) {     if(vtKey.size() != vtVal.size())     {         throw runtime_error( "Redis error" );     }       string strCmd = "MSET";     for(int i = 0; i < vtKey.size(); i++)     {         strCmd += " "+vtKey[i]+" "+vtVal[i];     }     cout << "strCmd:" << strCmd << endl;       void * r =  redisCommand(c, strCmd.c_str() );     if ( !r )         throw runtime_error( "Redis error" );     freeReplyObject( r ); }   void do_test( redisContext *c ) {         vector<string> vtKey;     vector<string> vtVal;       vtKey.push_back("A");     vtVal.push_back("AAAA");     vtKey.push_back("B");     vtVal.push_back("BBBB");     vtKey.push_back("C");     vtVal.push_back("CCCC");     //add a binary data     vtKey.push_back("D");     vtVal.push_back("");     char a[] = "ABCDE";     a[2] = 0;     vtVal[3].assign(a,5);       try     {         msetNotBinary(c, vtKey, vtVal );         //mset1( c, vtKey, vtVal );         //mset2( c, vtKey, vtVal );     }     catch ( runtime_error & )     {         cout << "Error" << endl;     } }   int main(int argc, char *argv[]) {     redisContext *c;       c = redisConnect("127.0.0.1",6379);     if (c->err)      {         cout << "Connection error: " << c->errstr << endl;         return -1;     }       do_test(c);       redisFree(c);       return 0; } 這種方式可以處理mset多個字符串數據,但對於數據內容為二進制數據的無能為力;   redisCommandArgv接口傳遞 方案   對於多個參數傳遞,hiredis提供了以下接口,這個接口中最後一個參數是所有的傳入數據的內容長度,  就是說這個接口是二進制安全的:   void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); 主要工作就是構造一個動態的二維數組char ** argv,其中涉及到char **到const char **的轉換,有一定的風險,  關於這一點前一篇文章已經談到;   void mset1( redisContext *c, const vector<string> &vtKey, const vector<string> & vtVal ) {     if(vtKey.size() != vtVal.size())     {         throw runtime_error( "Redis error" );     }       char ** argv = new char*[vtKey.size() + vtVal.size() + 1 ];     size_t * argvlen = new size_t[vtKey.size() + vtVal.size() + 1 ];       int j = 0;     argv[j] = new char[5];     memcpy(argv[j],"MSET",4);     argvlen[j] = 4;     ++j;         for(int i = 0 ; i < vtKey.size();i++)     {             argvlen[j] = vtKey[i].length();         argv[j] = new char[argvlen[j]];          memset((void*)argv[j],0,argvlen[j] );         memcpy((void*)argv[j],vtKey[i].data(),vtKey[i].length());         j++;           argvlen[j] = vtVal[i].length();         argv[j] = new char[argvlen[j]];         memset((void*)argv[j],0,argvlen[j]);         memcpy((void*)argv[j],vtVal[i].data(),vtVal[i].length());         j++;     }       //if not use const_cast<const char**> ,compile error     //for why assign from char** to const char** error, see my blog ...      void *r = redisCommandArgv(c, vtKey.size() + vtVal.size() + 1, const_cast<const char**>(argv), argvlen );     if ( !r )         throw runtime_error( "Redis error" );     freeReplyObject( r );       for(int i = 0;i < vtKey.size();i++)     {         delete [] argv[i];         argv[i] = NULL;     }       delete []argv;     delete []argvlen;     argv = NULL; } redisCommandArgv接口傳遞的Vector方案   還是使用redisCommandArgv接口,使用vector來構造這個const char **,這個方法是從參考資料1中學到的:   void mset2( redisContext *c, const vector<string> &vtKey, const vector<string> & vtVal) {     if(vtKey.size() != vtVal.size())     {         throw runtime_error( "Redis error" );     }       vector<const char *> argv( vtKey.size() + vtVal.size() + 1 );     vector<size_t> argvlen( vtKey.size() +  vtVal.size() + 1 );     int j = 0;       static char msetcmd[] = "MSET";     argv[j] = msetcmd;     argvlen[j] = sizeof(msetcmd)-1;     ++j;       for(int i = 0;i< vtKey.size();++i)     {         argvlen[j] = vtKey[i].length();         argv[j] = new char[argvlen[j]];          memset((void*)argv[j],0,argvlen[j] );         memcpy((void*)argv[j],vtKey[i].data(),vtKey[i].length());         j++;           argvlen[j] = vtVal[i].length();         argv[j] = new char[argvlen[j]];         memset((void*)argv[j],0,argvlen[j]);         memcpy((void*)argv[j],vtVal[i].data(),vtVal[i].length());         j++;     }       void *r = redisCommandArgv(c, argv.size(), &(argv[0]), &(argvlen[0]) );     if ( !r )         throw runtime_error( "Redis error" );     freeReplyObject( r ); } 這樣,就實現二進制數據的傳遞;   二進制校驗   程序執行後,可以用redis-cli來驗證:   對於非二進制安全的實現,二進制內容是截斷的: /opt/app/colin$./redis-cli get D "AB" 而二進制安全的實現接口,二進制數據的0通過轉義方式顯示: /opt/app/colin$./redis-cli get D "AB\x00DE"
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved