resp(REdis Serialization Protocol),可以看出resp就是一个序列化协议,resp具有实现简单,解析快捷,易读特性,看看jedis源码或使用抓包工具,都能看到resp协议数据。显然resp是二进制安全的,每个数据单元前面都有对应的长度标识。
基本只要看懂以下几行即可:
*2
$4
auth
$5
redis5
*+数字:表示数组长度
$+数字:表示字符串长度(字节长度)
auth处是redis的操作命令,如set,get等
以回车换行结尾。
客户端使用tcp连接和redis服务端通信,就是通常所说的socket编程了,只要socket连接到redis服务器,就可以发送resp协议数据到服务端了。
public class TestResp {
Socket socket;
public TestResp(Socket socket) {
this.socket = socket;
}
public TestResp(String host,int port) {
Socket socket = null;
try {
socket = new Socket(host, port);
} catch (IOException e) {
e.printStackTrace();
}
this.socket = socket;
}
static final String lineSeparator = System.getProperty("line.separator");
/** 发送auth指令 */
private void auth(String password) throws IOException {
StringBuffer authSb = new StringBuffer();
authSb.append("*2").append(lineSeparator);
authSb.append("$").append("auth".getBytes().length).append(lineSeparator);
authSb.append("auth").append(lineSeparator);
authSb.append("$").append(password.getBytes().length).append(lineSeparator);
authSb.append(password).append(lineSeparator);
OutputStream out = socket.getOutputStream();
out.write(authSb.toString().getBytes());
out.flush();
byte[] authResp = new byte[1024];
InputStream in = socket.getInputStream();
in.read(authResp);
System.out.println(String.format("auth result: %s", new String(authResp)));
}
/** 发送set指令 */
private void set(String key, String value) throws IOException {
StringBuffer setSb = new StringBuffer();
setSb.append("*3").append(lineSeparator);
setSb.append("$3").append(lineSeparator);
setSb.append("set").append(lineSeparator);
setSb.append("$").append(key.getBytes().length).append(lineSeparator);
setSb.append(key).append(lineSeparator);
setSb.append("$").append(value.getBytes().length).append(lineSeparator);
setSb.append(value).append(lineSeparator);
OutputStream out = socket.getOutputStream();
out.write(setSb.toString().getBytes());
out.flush();
byte[] setResp = new byte[1024];
InputStream in = socket.getInputStream();
in.read(setResp);
System.out.println(String.format("set resp: %s", new String(setResp)));
}
/** 发送set指令 */
private String get(String key) throws IOException {
StringBuffer getSb = new StringBuffer();
getSb.append("*2").append(lineSeparator);
getSb.append("$3").append(lineSeparator);
getSb.append("get").append(lineSeparator);
getSb.append("$").append(key.getBytes().length).append(lineSeparator);
getSb.append(key).append(lineSeparator);
OutputStream out = socket.getOutputStream();
out.write(getSb.toString().getBytes());
out.flush();
InputStream in = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
reader.readLine();
return reader.readLine();
}
public static void main(String[] args) throws IOException {
/*System.getProperties().forEach((k, v) -> {
System.out.println(k + ":" + v);
});*/
TestResp resp = new TestResp("127.0.0.1", 6379);
resp.auth("redis5");
resp.set("name","moon");
System.out.println(String.format("get result: %s", resp.get("name")));
}
}
以上使用java socket实现了redis基本操作命令:auth,set,get,其他命令类似。