国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

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

2020-01-26 15:03:50
字體:
來源:轉載
供稿:網友

需求

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"

完整可執行的代碼詳見github:https://github.com/me115/cppset/tree/master/2DimArray

以上所述就是本文的全部內容了,希望大家能夠喜歡。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 广汉市| 荥经县| 紫云| 科技| 镇坪县| 遂宁市| 新巴尔虎右旗| 罗源县| 周至县| 衡阳县| 阿坝| 萨迦县| 长顺县| 会东县| 宁德市| 兰溪市| 哈巴河县| 印江| 东明县| 宜川县| 白河县| 巍山| 墨江| 定日县| 晋宁县| 麦盖提县| 蕉岭县| 遂川县| 宜兴市| 盐城市| 临武县| 双桥区| 宁明县| 会同县| 壶关县| 那坡县| 荔波县| 贵德县| 富民县| 安塞县| 鄂州市|