C + + Redis mset binary Data Interface encapsulation scheme
Demand
Use the Hiredis Client interface to access Redis in C + +;
You need to use Mset to set up multiple binary data at once
The following gives three kinds of package realization scheme;
Simple splicing Scheme
In Redis-cli, the syntax for Mset is this:
/opt/colin$./redis-cli mset a 11 b 22 c 333OK
Following such a syntax concatenation, directly using the Hiredis string interface Rediscommand pass:
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 way can deal with Mset multiple string data, but the data content of binary data is powerless;
REDISCOMMANDARGV Interface Transfer Scheme
For multiple parameter passes, HIREDIS provides the following interface, the last parameter in this interface is the content length of all incoming data,
This means that the interface is binary safe:
void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
The main work is to construct a dynamic two-dimensional array char * * argv, which involves the conversion of char * * to const char * * , there is a certain risk,
The previous article on this point has been talked about;
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 for REDISCOMMANDARGV interface transfer
or using the REDISCOMMANDARGV interface, the vector is used to construct this const char * *, which is learned from reference 1:
void Mset2 (Rediscontext *c, const vector<string> &vtkey, const vector<string> & vtval) {if (vtkey.s Ize ()! = 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, the transfer of binary data is realized;
Binary checksum
After the program executes, you can use REDIS-CLI to verify:
对于非二进制安全的实现,二进制内容是截断的:/opt/app/colin$./redis-cli get D"AB"而二进制安全的实现接口,二进制数据的0通过转义方式显示:/opt/app/colin$./redis-cli get D"AB\x00DE"
Full executable code See Github:https://github.com/me115/cppset/tree/master/2dimarray
Resources
https://gist.github.com/dspezia/1455082
Posted by: Big CC | 8jan,2015
Blog: blog.me115.com [Subscribe]
Weibo: Sina Weibo
C + + Redis mset binary Data Interface encapsulation scheme