C ++ Redis mset binary data interface Encapsulation Scheme, redismset
C ++ Redis mset binary data interface Encapsulation Scheme
Requirement
Use the hiredis client interface in C ++ to access redis;
You need to use mset to set multiple binary data at a time.
Three packages are provided below;
Simple splicing Scheme
In redis-cli, The mset syntax is as follows:
/opt/colin$./redis-cli mset a 11 b 22 c 333OK
After splicing according to this syntax, use the hiredis string interface redisCommand to pass it directly:
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;}
This method can process multiple string data in mset, but there is nothing to do with binary data;
RedisCommandArgv interface transfer scheme
Hiredis provides the following interface for passing multiple parameters. The last parameter in this interface is the content length of all incoming data,
That is to say, this interface is binary secure:
void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
The main task is to construct a dynamic two-dimensional array.Char ** argv, Which involvesChar **ToConst char **There is a certain risk of conversion,
This is already mentioned in the previous article;
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;}
Vector scheme transmitted by redisCommandArgv Interface
Or use the redisCommandArgv interface and vector to construct this const char **. This method is learned from reference 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 );}
In this way, binary data is transmitted;
Binary Verification
After the program is executed, you can use redis-cli for verification:
For non-binary security implementation, the binary content is truncated:/opt/app/colin $. /redis-cli get D "AB" and binary security implementation interface. The binary data 0 is displayed in Escape mode:/opt/app/colin $. /redis-cli get D "AB \ x00DE"
Complete executable code can be found at github: https://github.com/me115/cppset/tree/master/2DimArray
References
Https://gist.github.com/dspezia/1455082
Posted by: CC | 8JAN, 2015
Blog: blog.me115.com [subscription]
Weibo: Sina Weibo