当前位置:网站首页>Implement the redis simple client customized based on socket

Implement the redis simple client customized based on socket

2022-06-24 20:22:00 Maple honey pomelo tea

One 、RESP agreement

First of all, understand ,Redis It's a CS framework Software for , Communication is generally divided into two steps ( barring pipeline and PubSub):

  • client (client) To the server (server) Send a command
  • The server parses and executes commands , Return the response result to the client Therefore, the format of the command sent by the client 、 The format of the server response result must have a specification , This specification is the communication protocol .

And in the Redis It is used in RESP(Redis Serialization Protocol) agreement :

  • Redis 1.2 Version introduced RESP agreement
  • Redis 2.0 In the version, it becomes the same as Redis The standard of server communication , be called
  • RESP2 Redis 6.0 In the version , from RESP2 Upgrade to RESP3 agreement , Add more data types and support 6.0 New features -- Client cache  

         stay RESP in , Distinguish different data types by the characters of the first byte , Common data types include 5 Kind of :

  1. Single line string : The first byte is ‘+’ , Followed by a single line string , With CRLF( "\r\n" ) ending . Such as return "OK": "+OK\r\n"
  2. error (Errors): The first byte is ‘-’ , Same format as single line string , It's just that the string is an exception message , for example :"-Error message\r\n"
  3. The number : The first byte is ‘:’ , Followed by a string in numeric format , With CRLF ending . for example :":10\r\n"
  4. Multiline string : The first byte is ‘$’ , A string representing binary security , The biggest support 512MB: If the size is 0, Represents an empty string :"$0\r\n\r\n" If the size is -1, It means it doesn't exist :"$-1\r\n"
  5. Array : The first byte is ‘*’, Followed by the number of array elements , Keep up with the elements , The element data type is unlimited : for example

 

         

  Two 、 simulation redis Client implementation

【 Response resolution request module 】


    /**
     *  Parsing response request information 
     *
     * @return  Analysis results 
     */
    private static Object handleResponse() throws IOException {
        // There are five ways to read data 
        int opt = READER.read();
        switch (opt) {
            case '+':// Single line string , Read single line information 
                return READER.readLine();
            case '-':// Abnormal information , Exception returned from reading single line information 
                return READER.readLine();
            case ':':// value type , Read single line 
                return Long.parseLong(READER.readLine());
            case '*':
                return readBulkString();
            case '$':// Read multi line string 
                int len = Integer.parseInt(READER.readLine());
                if (len == -1) {
                    return null;
                } else if (len == 0) {
                    return "";
                } else {
                    return READER.readLine();
                }
            default:
                throw new RuntimeException(" Bad data format !");
        }
    }


    /**
     *  Array result parsing 
     *
     * @return
     * @throws IOException
     */
    private static Object readBulkString() throws IOException {
        // Get array size 
        int size = Integer.parseInt(READER.readLine());
        if (size <= 0) {
            return null;
        } else {
            List<Object> result = new ArrayList<>();
            for (int i = 0; i < size; i++) {
                result.add(handleResponse());
            }
            return result;
        }
    }

【 Complete code 】

/**
 * @Author  Honey grapefruit tea 
 * @Date 2022/6/14 20:34
 */
public class MyRedisClient {

    private static Socket socket;

    private static PrintWriter WRITER;
    private static BufferedReader READER;
    private static BufferedReader KEYBOARD_INPUT;

    private static final String INFO = "127.0.0.1:6379> ";

    public static void main(String[] args) throws Exception {
        try {
            // Establishing a connection 
            // virtual machine IP Address :192.168.29.128
            socket = new Socket("192.168.29.128", 6379);
            // Get input stream 、 Output stream 
            WRITER = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8));
            READER = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
            // Keyboard input command 
            KEYBOARD_INPUT = new BufferedReader(new InputStreamReader(System.in));
            // Carry out orders , At the same time, the result is analyzed 
            execute();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // Release the connection 
            try {
                if (READER != null)
                    READER.close();
                if (WRITER != null)
                    WRITER.close();
                if (socket != null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     *  Get keyboard input 
     *
     * @return
     * @throws Exception
     */
    public static String getInput() throws Exception { //  Keyboard information input 
        System.out.print(INFO);
        return KEYBOARD_INPUT.readLine();
    }

    /**
     *  Carry out orders 
     *
     * @throws IOException
     */
    private static void execute() throws Exception {
        while (true) {
            // Get input command , Remove the first space 
            String string = getInput().trim();
            // Parse command , Remove all spaces 
            String replace = string.replaceAll("\\s{1,}", "/");
            //System.out.println(replace);
            String[] strings = replace.split("/");
            // Send a request 
            sendRequest(strings);
            // Parsing response information 
            Object result = handleResponse();
            if (result == null) {
                System.out.println(getFormatResult("null", "warning"));
            } else if (result.toString().startsWith("ERR")) {
                System.out.println(getFormatResult(result.toString(), "error"));
            } else {
                System.out.println(getFormatResult(result.toString(), "info"));
            }
        }
    }

    /**
     *  Format output 
     *
     * @param content  result 
     * @param type     type 
     * @return  Format output 
     */
    private static String getFormatResult(String content, String type) {
        if (type.equals("error")) {
            return String.format("\033[%dm%s\033[0m", 31, content);
        } else if (type.equals("info")) {
            return String.format("\033[%dm%s\033[0m", 34, content);
        } else if (type.equals("warning")) {
            return String.format("\033[%dm%s\033[0m", 33, content);
        } else {
            return content;
        }
    }

    /**
     *  Parsing response request information 
     *
     * @return  Analysis results 
     */
    private static Object handleResponse() throws IOException {
        // There are five ways to read data 
        int prefix = READER.read();
        switch (prefix) {
            case '+':// Single line string , Read single line information 
                return READER.readLine();
            case '-':// Abnormal information , Exception returned from reading single line information 
                return READER.readLine();
            case ':':// value type , Read single line 
                return Long.parseLong(READER.readLine());
            case '*':
                return readBulkString();
            case '$':// Read multi line string 
                int len = Integer.parseInt(READER.readLine());
                if (len == -1) {
                    return null;
                } else if (len == 0) {
                    return "";
                } else {
                    return READER.readLine();
                }
            default:
                throw new RuntimeException(" Bad data format !");
        }
    }

    /**
     *  Array result parsing 
     *
     * @return
     * @throws IOException
     */
    private static Object readBulkString() throws IOException {
        // Get array size 
        int size = Integer.parseInt(READER.readLine());
        if (size <= 0) {
            return null;
        } else {
            List<Object> result = new ArrayList<>();
            for (int i = 0; i < size; i++) {
                result.add(handleResponse());
            }
            return result;
        }
    }

    /**
     *  Send request information 
     *
     * @param args
     */
    private static void sendRequest(String... args) {
        // It is essentially an order --> set name XXXX
        WRITER.println("*" + args.length);
        for (String arg : args) {
            WRITER.println("$" + arg.getBytes(StandardCharsets.UTF_8).length);
            WRITER.println(arg);
        }
        // Empty buffer 
        WRITER.flush();
    }
}

3、 ... and 、 Effect display

【 simulation redis-cli】idear window  

win The console output color is garbled , Color escape is not supported .


If articles are useful to you , Let's support them for three times !!!

原网站

版权声明
本文为[Maple honey pomelo tea]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/175/202206241353092889.html