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);
}
}