C++訪問Redis的mset 二進(jìn)制數(shù)據(jù)接口封裝方案
需求
C++中使用hiredis客戶端接口訪問redis;
需要使用mset一次設(shè)置多個二進(jìn)制數(shù)據(jù)
以下給出三種封裝實現(xiàn)方案;
簡單拼接方案
在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多個字符串?dāng)?shù)據(jù),但對于數(shù)據(jù)內(nèi)容為二進(jìn)制數(shù)據(jù)的無能為力;
redisCommandArgv接口傳遞 方案
對于多個參數(shù)傳遞,hiredis提供了以下接口,這個接口中最后一個參數(shù)是所有的傳入數(shù)據(jù)的內(nèi)容長度,
就是說這個接口是二進(jìn)制安全的:
void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
主要工作就是構(gòu)造一個動態(tài)的二維數(shù)組char ** argv,其中涉及到char **到const char **的轉(zhuǎn)換,有一定的風(fēng)險,
關(guān)于這一點前一篇文章已經(jīng)談到;
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來構(gòu)造這個const char **,這個方法是從參考資料1中學(xué)到的:
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 ); }
這樣,就實現(xiàn)二進(jìn)制數(shù)據(jù)的傳遞;
二進(jìn)制校驗
程序執(zhí)行后,可以用redis-cli來驗證:
對于非二進(jìn)制安全的實現(xiàn),二進(jìn)制內(nèi)容是截斷的:
/opt/app/colin$./redis-cli get D
"AB"
而二進(jìn)制安全的實現(xiàn)接口,二進(jìn)制數(shù)據(jù)的0通過轉(zhuǎn)義方式顯示:
/opt/app/colin$./redis-cli get D
"AB\x00DE"
完整可執(zhí)行的代碼詳見github:https://github.com/me115/cppset/tree/master/2DimArray
以上所述就是本文的全部內(nèi)容了,希望大家能夠喜歡。
上一篇:C++ Custom Control控件向父窗體發(fā)送對應(yīng)的消息
欄 目:C語言
本文標(biāo)題:C++訪問Redis的mset 二進(jìn)制數(shù)據(jù)接口封裝方案
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/3014.html
您可能感興趣的文章
- 04-02c語言沒有round函數(shù) round c語言
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實現(xiàn)全排列算法的方法詳解
- 01-10c++中inline的用法分析
- 01-10用C++實現(xiàn)DBSCAN聚類算法
- 01-10全排列算法的非遞歸實現(xiàn)與遞歸實現(xiàn)的方法(C++)
- 01-10C++大數(shù)模板(推薦)
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解
- 01-10深入C/C++浮點數(shù)在內(nèi)存中的存儲方式詳解
- 01-10深入理解C/C++混合編程


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機閱讀
- 01-10delphi制作wav文件的方法
- 04-02jquery與jsp,用jquery
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-11ajax實現(xiàn)頁面的局部加載
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10C#中split用法實例總結(jié)
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10使用C語言求解撲克牌的順子及n個骰子