C # implement the redis client (1 ),
Introduction
The redis client needs to be transformed in recent project use. Let's take a look at the document.
Directory
I. protocol specifications
Ii. Basic Communication
Iii. STATUS Command
Iv. set and get commands
V. Pipelines and transactions
Vi. Summary
I. protocol specifications
Redis allows clients to connect over TCP. The default port is port 6379. All transmitted data ends with \ r \ n.
Request format
* <Number of arguments> \ r \ n $ <number of bytes of argument 1> \ r \ n<Argument data> \ r \ n
Example: * 1 \ r \ n $4 \ r \ nINFO \ r \ n
Response format
1: simple string, non-binary secure string, usually status reply. +, For example, + OK \ r \ n
2: error message. -Start with-ERR unknown command 'mush '\ r \ n
3: integer. : Start with, for example: 1 \ r \ n
4: large block reply value, up to 512 MB. $ Starts with + Data Length. Example: $4 \ r \ mush \ r \ n
5: Multiple replies. *, For example, * 2 \ r \ n $3 \ r \ nfoo \ r \ n $3 \ r \ nbar \ r \ n
Ii. Basic Communication
Define the configuration class:
Public class Configuration {public string Host {get; set;} public int Port {get; set ;}/// <summary> // whether the Socket is using the Nagle algorithm. /// </Summary> public bool NoDelaySocket {get; set;} public Configuration () {Host = "localhost"; Port = 6379; NoDelaySocket = false ;}}
Implement socket connection:
Public class RedisBaseClient {// Configuration file private configuration Configuration; // communication socket private Socket socket; // receiving byte array private byte [] ReceiveBuffer = new byte [100000]; public RedisBaseClient (Configuration config) {configuration = config;} public RedisBaseClient (): this (new Configuration () {} public void Connect () {if (socket! = Null & socket. connected) return; socket = new Socket (AddressFamily. interNetwork, SocketType. stream, ProtocolType. tcp) {NoDelay = configuration. noDelaySocket}; socket. connect (configuration. host, configuration. port); if (socket. connected) return; Close () ;}/// <summary >/// Close client /// </summary> public void Close () {socket. disconnect (false); socket. close ();}}
Call:
RedisBaseClient redis = new RedisBaseClient();redis.Connect();
Server success response:
Iii. STATUS Command
Define Redis command enumeration:
Public enum RedisCommand {GET, // GET the value of a key INFO, // Redis information. SET, // Add a value EXPIRE, // SET the expiration time MULTI, // mark a transaction block to start EXEC, // execute all the commands issued after MULTI}
Sending command construction:
Public string SendCommand (RedisCommand command, params string [] args) {// Request Header Format, * <number of arguments> \ r \ n const string headstr = "* {0} \ r \ n "; // parameter information $ <number of bytes of argument N> \ r \ n <argument data> \ r \ n const string bulkstr = "$ {0} \ r \ n {1} \ r \ n "; var sb = new StringBuilder (); sb. appendFormat (headstr, args. length + 1); var cmd = command. toString (); sb. appendFormat (bulkstr, cmd. length, cmd); foreac H (var arg in args) {sb. appendFormat (bulkstr, arg. length, arg);} byte [] c = Encoding. UTF8.GetBytes (sb. toString (); try {Connect (); socket. send (c); socket. receive (ReceiveBuffer); Close (); return ReadData ();} catch (SocketException e) {Close ();} return null;} private string ReadData () {var data = Encoding. UTF8.GetString (ReceiveBuffer); char c = data [0]; // check the error message. If (c = '-') // exception handling. Throw new Exception (data); // returns a status response. If (c = '+') return data ;}
Call:
private void button1_Click(object sender, EventArgs e) { RedisBaseClient redis = new RedisBaseClient(); var result = redis.SendCommand(RedisCommand.INFO); richTextBox1.Text = result; }
Response output. 937 is the data length.
Iv. set and get commands
Call:
private void button2_Click(object sender, EventArgs e) { RedisBaseClient redis = new RedisBaseClient(); var result = redis.SendCommand(RedisCommand.SET, "msg", "testvalue"); richTextBox1.Text = result.ToString(); } private void button3_Click(object sender, EventArgs e) { RedisBaseClient redis = new RedisBaseClient(); var result = redis.SendCommand(RedisCommand.GET, "msg"); richTextBox1.Text = result.ToString(); }
Output
MULTI, EXEC command, atomic operation. The pipeline is to send commands (without waiting for the last command to reply), enter the command queue, then execute multiple commands once, and return the client results.
We usually use the ServiceStack. Redis client to directly set, which is actually two Commands: set and expire. The simple implementation is as follows:
Public void CreatePipeline () {SendCommand (RedisCommand. MULTI, new string [] {}, true);} public string EnqueueCommand (RedisCommand command, params string [] args) {return SendCommand (command, args, true );} public string FlushPipeline () {var result = SendCommand (RedisCommand. EXEC, new string [] {}, true); Close (); return result;} public string SendCommand (RedisCommand command, string [] args, bool IsPipeline = false) {// Request Header Format, * <number of arguments> \ r \ n const string headstr = "* {0} \ r \ n "; // parameter information $ <number of bytes of argument N> \ r \ n <argument data> \ r \ n const string bulkstr = "$ {0} \ r \ n {1} \ r \ n "; var sb = new StringBuilder (); sb. appendFormat (headstr, args. length + 1); var cmd = command. toString (); sb. appendFormat (bulkstr, cmd. length, cmd); foreach (var arg in args) {sb. appendFormat (bulkstr, arg. Length, arg);} byte [] c = Encoding. UTF8.GetBytes (sb. toString (); try {Connect (); socket. send (c); socket. receive (ReceiveBuffer); if (! IsPipeline) {Close () ;}return ReadData () ;}catch (SocketException e) {Close () ;}return null ;} public string SetByPipeline (string key, string value, int second) {this. createPipeline (); this. enqueueCommand (RedisCommand. SET, key, value); this. enqueueCommand (RedisCommand. EXPIRE, key, second. toString (); return this. flushPipeline ();}
Call:
private void button4_Click(object sender, EventArgs e) { RedisBaseClient redis = new RedisBaseClient(); richTextBox1.Text = redis.SetByPipeline("cnblogs", "mushroom", 1000); }
Output:
Two replies.
Vi. Summary
This article is just a simple implementation. If you are interested, continue. Ps: a little repetitive.
The Socket connection pool management is more complicated when the client implements this.
Reference resources
1: http://redis.io/topics/protocol
2: https://github.com/ServiceStack/ServiceStack.Redis
If you have any errors, please point out the correct ones. If it is helpful to you, we recommend n (* too many errors *) n.
Author: Mr. mushroom
Source: http://www.cnblogs.com/mushroom/p/4217541.html