C # implement the redis client (1 ),

Source: Internet
Author: User

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

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.