`

RESP

 
阅读更多

转自:https://www.jianshu.com/p/daa3cb672470

 

Redis服务器与客户端通过RESP(REdis Serialization Protocol)协议通信。

RESP协议支持的数据类型

以下例子都是展示redis返回的真实值,在redis客户端会把返回数据的前缀去掉

Simple String第一个字节以+开头,随后紧跟内容字符串(不能包含CR LF),最后以CRLF结束。很多Redis命令执行成功时会返回"OK","OK"就是一个Simple String

 "+OK\r\n"

 

Error的结构与Simple String很像,但是第一个字节以-开头:

"-ERR unknown command 'foobar\r\n'"

-符号后的第一个单词代表错误类型,ERR代表一般错误,WRONGTYPE代表在某种数据结构上执行了不支持的操作。

 

Integer第一个字节以:开头,随后紧跟数字,以CRLF结束:

":1000\r\n"

很多Redis命令会返回Integer,例如INCR LLEN等。

 

Bulk String是一种二进制安全的字符串结构,整个结构包含两部分。第一部分以$开头,后面紧跟字符串的字节长度,CRLF结尾。第二部分是真正的字符串内容,CRLF结尾,最大长度限制为512MB。一个Bulk String结构的"Hello World!"是:

"$12\\r\\nHello World!\\r\\n"

空字符串是:

"$0\\r\\n\\r\\n"

nil是:

"$-1\\r\\n"

 

Array也可以看成由两部分组成,第一部分以*开头,后面紧跟一个数字代表Array的长度,以CRLF结束。第二部分是每个元素的具体值,可能是Integer,可能是Bulk StringArray结构的["hello", "world"]是:

"*2\\r\\n$5\\r\\nhello\\r\\n$5\\r\\nworld\\r\\n"

Array

"*-1\\r\\n"

 

要注意一点,RESP的数据类型和redis的数据类型不一样,他们之间的关系是在数据传输中RESP的数据类型能够表达所有的redis数据类型,比如redis中有个hash数据类型

 

127.0.0.1:6379>  HMSET runoobkey name "redis tutorial" description "redis basic commands for caching" likes 20 visitors 23000
OK
127.0.0.1:6379>  HGETALL runoobkey
1) "name"
2) "redis tutorial"
3) "description"
4) "redis basic commands for caching"
5) "likes"
6) "20"
7) "visitors"
8) "23000"
 这里RESP就是用Array来表达hash,

 

 

通过RESP协议与服务端通信

了解了Redis协议的基本数据类型,就可以通过Socket与Redis Server进行通信:

package me.likeyao.yingzong.example;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.charset.Charset;

/**
 * Created by yingzong on 16/6/15.
 */
public class SimpleProtocol {

    public static void main(String[] args) throws Exception{
        Socket socket = new Socket();
        //TIME_WAIT状态下可以复用端口
        socket.setReuseAddress(true);
        //空闲时发送数据包,确认服务端状态
        socket.setKeepAlive(true);
        //关闭Nagle算法,尽快发送
        socket.setTcpNoDelay(true);
        //调用close方法立即关闭socket,丢弃所有未发送的数据包
        socket.setSoLinger(true, 0);
        //连接server
        socket.connect(new InetSocketAddress("localhost", 6379), 3000);
        //设置读取时超时时间
        socket.setSoTimeout(3000);

        OutputStream os = socket.getOutputStream();
        /**
         * SET 命令
         * 协议: array 3个元素 SET simpleKey simpleValue
         */
        os.write(getBytes("*3\\r\\n$3\\r\\nSET\\r\\n$9\\r\\nsimpleKey\\r\\n$11\\r\\nsimpleValue\\r\\n"));
        os.flush();

        InputStream is = socket.getInputStream();

        /**
         * 解析SET命令的返回结果
         */
        String result = analysisResult(is);

        System.out.println("SET command response : " + result);
        System.out.println();

        /**
         * GET 命令
         * 协议: array 2个元素 GET simpleKey
         */
        os.write(getBytes("*2\\r\\n$3\\r\\nGET\\r\\n$9\\r\\nsimpleKey\\r\\n"));
        os.flush();

        /**
         * 解析GET命令返回结果
         */
        String value = analysisResult(is);
        System.out.println("GET command response : " + value);

        is.close();
        os.close();
        socket.close();
    }

    /**
     * 解析返回结果
     * @param is
     * @return
     * @throws Exception
     */
    private static String analysisResult(InputStream is) throws Exception{
        /**
         * 第一个字节指定返回的数据结构类型
         */
        byte type = (byte)is.read();

        System.out.println("response type is : " + (char)type);

        if(type == '+'){
            //Simple String类型
            return readCRLF(is);
        }else if(type == '$'){
            //Bulk String类型
            int len = readIntCRLF(is);
            System.out.println("$ value len : " + len);
            return readFixedLen(is, len);
        }

        return null;
    }

    /**
     * 读取int值,直到遇到CRLF
     * @param is
     * @return
     * @throws Exception
     */
    private static int readIntCRLF(InputStream is) throws Exception{
        return Integer.parseInt(readCRLF(is));
    }

    /**
     * 读取字符串,直到遇到CRLF
     * @param is
     * @return
     * @throws Exception
     */
    private static String readCRLF(InputStream is) throws Exception{
        byte b = (byte)is.read();
        StringBuilder sb = new StringBuilder();
        //不是最后一个输入字节时
        while(b != -1){
            //判断是否是CR,如果不是加入sb中
            if(b != '\\r'){
                sb.append((char)b);
            }else{
                //如果是CR,继续读取一个字节,如果不是LF,报错
                byte oneMore = (byte)is.read();
                if(oneMore != '\\n'){
                    throw new RuntimeException("CRLF error!");
                }else{
                    break;
                }
            }
            b = (byte)is.read();
        }
        return sb.toString();
    }

    /**
     * 读取固定字节长度的字符串
     * @param is
     * @param len
     * @return
     * @throws Exception
     */
    private static String readFixedLen(InputStream is, int len) throws Exception{
        byte[] bytes = new byte[len];
        for(int i = 0; i < len; i++){
            bytes[i] = (byte)is.read();
        }
        //CR
        is.read();
        //LF
        is.read();
        return new String(bytes, "UTF-8");
    }

    private static byte[] getBytes(String str) throws Exception{
        return str.getBytes(Charset.forName("UTF-8"));
    }

}


=>
response type is : +
SET command response : OK

response type is : $
$ value len : 11
GET command response : simpleValue

 

 

代码执行了两个命令:

SET simpleKey "simpleValue"  => "OK"
GET simpleKey => "simpleValue"

 analysisResult方法目前只支持了+ $两种格式的解析,其他格式解析方式类似,就不一一实现了。

 

分享到:
评论

相关推荐

    RESP.app GUI for Redis离线安装包下载

    **Redis桌面管理器RESP.app详解** Redis是一款高性能的键值对数据库,广泛应用于缓存、消息中间件等场景。为了方便开发者对Redis进行管理和操作,出现了各种图形化用户界面(GUI)工具,其中就包括了RESP.app,它...

    WIndows Redis可视化工具:resp-2022.1.0.0 GUI

    **Redis可视化工具RESP 2022.1.0.0 GUI详解** Redis,全名Remote Dictionary Server,是一款开源、高性能、支持网络、基于键值对的数据存储系统。在开发和运维过程中,为了方便地管理和操作Redis服务器,可视化工具...

    免费Redis图形化界面(RESP):resp-2022.5.zip

    标题提到的"免费Redis图形化界面(RESP):resp-2022.5.zip"是一个关于Resp的更新版本,其中包含了一款名为"resp-2022.5.0.0.exe"的可执行文件,这是RESP图形化管理工具的安装程序。用户可以通过这个程序在Windows...

    Redis及其管理工具:Redis-x64-5.0.14.1、RESP-app

    描述中提到的“RESP_app”是一个Redis响应协议(REdis Simple String Protocol)的应用程序,可能是一个图形用户界面(GUI)工具,用于管理和操作Redis服务器。RESP是Redis默认的通信协议,它使得客户端与服务器之间...

    redis可视化工具Windows(resp-2022.5)

    **Redis可视化工具Windows (RESP-2022.5)** Redis是一款开源、高性能的键值存储系统,常被用于数据库、缓存和消息中间件等场景。在管理Redis实例时,虽然可以通过命令行界面进行操作,但对于非开发人员或者需要更...

    resp-2022.5.1.0.exe

    rdm resp redis resp-2022.5.1 RedisDesktopManager 2022.5.1

    RESP软件(Redis图形化管理软件)

    RESP是一款的Redis图形化管理软件,免费、绿色,简洁、好用的工具,方便您管理Redis缓存数据库。

    resp-2022.5.0.0.exe

    在下载并安装 resp-2022.5.0.0.exe 文件后,只需按照安装向导的指示完成安装过程,然后启动 Redis Desktop Manager,即可开始你的 Redis 管理之旅。请注意,为了确保系统的安全性,务必备份重要数据,并定期更新软件...

    Redis连接工具resp-2022.5.1.exe下载

    下载,解压ZIP,运行resp-2022.5.1.exe安装

    mvn_resp.rar

    本资料"mvn_resp.rar"聚焦于Maven的响应式编程(Reactive Programming)特性,旨在帮助开发者深入理解并熟练运用这一技术。以下是关于Maven响应式编程的详细讲解。 一、Maven概述 Maven是由Apache软件基金会开发的...

    RedisDesktopManager 最新版本 RESP.app 2022.5 GUI for Redis

    最新版本 Redis 可视化客户端软件,RedisDesktopManager 最新版本 RESP.app 2022.5 GUI for Redis,Windows 64 位最新版本,安全可靠,下载直接安装可用。

    软件 redis 可视化客户端 resp

    resp 软件开发人员 redis 可视化客户端

    redis之resp界面连接

    redis之resp界面连接

    redis windows最终版 RESP.app-RedisDesktopManager-2022.5.zip

    4. 使用Redis Desktop Manager:现在,你可以打开下载的"RESP.app_RedisDesktopManager_2022.5.exe"文件,安装并启动Redis Desktop Manager。在应用程序中,输入Redis服务器的IP地址(对于本地安装通常是`127.0.0.1`...

    HttpClient问题:The server failed to respond with a valid HTTP resp

    在使用Apache HttpClient进行HTTP通信时,可能会遇到"HttpClient问题:The server failed to respond with a valid HTTP resp"这样的异常。这个错误通常表示服务器未能返回一个有效的HTTP响应,这可能是由多种原因...

    resp-2022.0.0.0.exe

    RedisDesktopManager 2022.0.0.0

    resp-2022.4.2.0.exe

    RedisDesktopManager 2022.4.2.0

    resp-2022.3.0.0.exe

    99,00¥下载,无偿分享给大家 Redis Desktop Manager – Redis可视化管理工具 2022.3 windows 最新版本redis客户端管理工具 windows 64位 已编译好的安装程序(编译之路漫长,此程序由官方编译) ...

    resp-2022.3.0.0.dmg

    resp-2022.3.0.0

    resp-2022.1.0.0.exe

    RedisDesktopManager 2022.1.0.0

Global site tag (gtag.js) - Google Analytics