redis(5)协议:socket通讯 & resp协议

本文介绍了Socket编程的基础概念,展示了服务端和客户端的代码实现,以及如何使用Resp协议进行数据交换,包括模拟Redis服务器和使用Jedis客户端操作。重点讲解了Resp协议的特点和格式,以及手写Jedis客户端的步骤。
摘要由CSDN通过智能技术生成

1、Socket快速入门

1.1 概念

Socket是进程通讯的一种方式,即调用这个网络库的一些API函数实现分布在不同主机的相关进程之间的数据交换。

1.2 流程

在这里插入图片描述

1.3 代码实现
1.3.1 服务端
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(8888);
        //代码阻塞(等待客户端连接)
        Socket socket = serverSocket.accept();

        //把消息读到byte数组里面
        InputStream reader = socket.getInputStream();
        byte[] request = new byte[1024];
        reader.read(request);

        //转化成string 输出
        String req = new String(request);
        System.out.println(req);

        serverSocket.close();

    }
}
1.3.2 客户端
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Client {

    public static void main(String[] args)  throws  Exception{
        //连接上Server
        Socket socket = new Socket("127.0.0.1", 8888);
        //获得输出流
        OutputStream writer = socket.getOutputStream();

        //发送信息给服务端
        writer.write("你好,Redis!".getBytes());
        socket.close();
    }
}

2、Resp概述

基于TCP的应用层协议 RESP (REdis Serialization Protocol)。
RESP底层采用的是TCP的连接方式,通过tcp进行数据传输,然后根据解析规则解析相应信息,完成交互。

2.1 特点
  • 容易实现
  • 解析快
  • 人类可读
2.2 Resp官网介绍

https://redis.io/topics/protocol

2.2.1 模拟RedisVM
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class RedisVM {

    //模拟Redis服务端,用于拦截Redis客户端的消息
    public static void main(String[] args) throws  Exception{

        ServerSocket serverSocket = new ServerSocket(6378);

        Socket socket = serverSocket.accept();

        byte[] request = new byte[1024];

        InputStream inputStream = socket.getInputStream();

        inputStream.read(request);

        //输出
        System.out.println(new String(request));
        socket.close();
        serverSocket.close();
    }
}
2.2.2 模拟测试
import org.junit.Test;
import redis.clients.jedis.Jedis;

public class RedisTest {

    @Test
    public void jedisSet(){
        Jedis jedis=new Jedis("127.0.0.1",6379);
        jedis.set("name","小明");
        jedis.close();
    }

    @Test
    public void jedisGet(){
        Jedis jedis=new Jedis("127.0.0.1",6379);
        jedis.get("name");
        jedis.close();
    }

    @Test
    public void jedisTest() throws Exception {
        EnjoyRedisClient redisClient=new EnjoyRedisClient();
        redisClient.set("name","liqiu");

        String name = redisClient.get("name");
        System.out.println("开始打印:");
        System.out.println(name);
        System.out.println("打印结束");
    }
}
2.3 Resp格式
  • 数组类型 Arrays,以 ""星号开头
    格式:
    数组元素个数 \r\n
  • 大字符串类型 Bulk Strings, 以 "$"美元符号开头
    格式:
    $ 字符串的长度 \r\n
    字符串 \r\n
2.4 基于Resp实现手写Jedis
2.4.1 初始化
public class EnjoyRedisClient {
	Socket socket;
	InputStream reader;
	OutputStream writer;

	public EnjoyRedisClient() throws Exception {
		socket = new Socket("localhost", 6379);
		reader = socket.getInputStream();
		writer = socket.getOutputStream();
	}
2.4.2 Set方法实现
	public String set(String k, String v) throws Exception {
		StringBuffer command = new StringBuffer();
		command.append("*3").append("\r\n");
		command.append("$3").append("\r\n");
		command.append("SET").append("\r\n");
		command.append("$").append(k.getBytes().length).append("\r\n");
		command.append(k).append("\r\n");
		command.append("$").append(v.getBytes().length).append("\r\n");
		command.append(v).append("\r\n");

		writer.write(command.toString().getBytes());
		byte[] reponse = new byte[1024];
		reader.read(reponse);
		return new String(reponse);
	}
2.4.3 Get方法实现
	public String get(String k) throws Exception {
		StringBuffer command = new StringBuffer();
		command.append("*2").append("\r\n");
		command.append("$3").append("\r\n");
		command.append("GET").append("\r\n");
		command.append("$").append(k.getBytes().length).append("\r\n");
		command.append(k).append("\r\n");

		writer.write(command.toString().getBytes());

		byte[] reponse = new byte[1024];
		reader.read(reponse);

		return new String(reponse);
	}
2.4.4 完整代码(直接连接Redis服务端)
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class EnjoyRedisClient {
	Socket socket;
	InputStream reader;
	OutputStream writer;

	public EnjoyRedisClient() throws Exception {
		socket = new Socket("localhost", 6379);
		reader = socket.getInputStream();
		writer = socket.getOutputStream();
	}


	public String set(String k, String v) throws Exception {
		StringBuffer command = new StringBuffer();
		command.append("*3").append("\r\n");
		command.append("$3").append("\r\n");
		command.append("SET").append("\r\n");
		command.append("$").append(k.getBytes().length).append("\r\n");
		command.append(k).append("\r\n");
		command.append("$").append(v.getBytes().length).append("\r\n");
		command.append(v).append("\r\n");

		writer.write(command.toString().getBytes());
		byte[] reponse = new byte[1024];
		reader.read(reponse);
		return new String(reponse);
	}

	public String get(String k) throws Exception {
		StringBuffer command = new StringBuffer();
		command.append("*2").append("\r\n");
		command.append("$3").append("\r\n");
		command.append("GET").append("\r\n");
		command.append("$").append(k.getBytes().length).append("\r\n");
		command.append(k).append("\r\n");

		writer.write(command.toString().getBytes());

		byte[] reponse = new byte[1024];
		reader.read(reponse);

		return new String(reponse);
	}

}

上一章:redis(四) 持久化策略:RDB&AOF

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值