【Redis学習】redis通信プロトコル
14048 ワード
サービスは抽象的な概念であり、使用者が何らかのニーズを達成することを支援することを意図している.ネットワークサービスでは、通常、ユーザがネットワークを介して対話し、所望の情報を得るオペレーティングシステム上で実行されるプログラムとして定義することができる.
クライアントとサーバは、TCP接続によってデータインタラクションを行うため、他のネットワークサービスと同様にプロトコルがあります.redisサーバは、コマンドおよびコマンドのパラメータを受け入れます.サーバは、コマンドを受信した後にコマンドを処理し、コマンドの返信をクライアントに送信します.具体的には、ネットワーク層上では、RedisはTCPポート6379上で到来する接続を傍受し、クライアント接続が到来すると、RedisサーバはこのためにTCP接続を作成する.クライアントとサーバの間で送信される各Redisコマンドまたはデータは、rで終了します.
redisの通信プロトコルには、メッセージヘッダ識別とメッセージ行が含まれており、メッセージ行にはデータブロックサイズの説明がある可能性があります.redisは行で区分され、各行はrで終了し、各行にメッセージヘッダがある.
メッセージ・ボディには、次の5つのタイプがあります.
redisコマンドは、複数の異なるタイプの返信を返します.サーバから送信されたデータの最初のバイトを確認することで、この返信のタイプを決定できます.
具体的な指令と返却:
1、SET
MYTESTの値をHELLOに設定します.redisの通信プロトコルでは、コマンドをスペースで3行に分割し、最終的なコマンドは次のとおりです.
server:サービス側操作成功:+OKrサービス側がエラーを返した場合:-エラー情報r
2、GET
生成された通信命令:
server:このkeyが存在する場合は、次を返します.
3、HKEYS
以上のコマンドは、MYTESTに対応するfieldメンバーの数を取得します.
server:フィールド情報が存在しない場合:*0r AGEフィールド情報が存在する場合:
4、HMGET
以上のコマンドは、HENRYのQQ情報を取得します.
server :
フィールド値が存在しない場合
フィールド値の存在
以上は主にRedisの一般的な処理のいくつかの情況を列挙して、指令が多すぎるため一つ一つ列挙しないで、もし自分でClientを実現する必要がある友达がRedisの公式に関連する命令のドキュメントを見ることができます.redis公式ドキュメント
練習ウィジェット:socketとredis serverで通信する
実行結果;
クライアントとサーバは、TCP接続によってデータインタラクションを行うため、他のネットワークサービスと同様にプロトコルがあります.redisサーバは、コマンドおよびコマンドのパラメータを受け入れます.サーバは、コマンドを受信した後にコマンドを処理し、コマンドの返信をクライアントに送信します.具体的には、ネットワーク層上では、RedisはTCPポート6379上で到来する接続を傍受し、クライアント接続が到来すると、RedisサーバはこのためにTCP接続を作成する.クライアントとサーバの間で送信される各Redisコマンドまたはデータは、rで終了します.
redisの通信プロトコルには、メッセージヘッダ識別とメッセージ行が含まれており、メッセージ行にはデータブロックサイズの説明がある可能性があります.redisは行で区分され、各行はrで終了し、各行にメッセージヘッダがある.
メッセージ・ボディには、次の5つのタイプがあります.
(1)[+]は正しい状態情報を表し、具体的な情報は:現在の行+後の文字(2)[-]はエラー情報を表し、具体的な情報は:現在の行-後の文字(3)[]はメッセージ体が全部で何行あるかを表し、現在の行を含まず、後に具体的な行数(4)[]は次の行のデータ長を表し、改行記号rの長さを含まない、]は次の行のデータ長を表し、改行記号rの長さは含まれておらず、後に対応する長さのデータ(5)[:]は、対応する数値を返します。
redisコマンドは、複数の異なるタイプの返信を返します.サーバから送信されたデータの最初のバイトを確認することで、この返信のタイプを決定できます.
(1)状態回復の1バイト目が[+](2)エラー回復の1バイト目が[-](3)整数回復の1バイト目が[:](4)一括回復の1バイト目が[$](5)複数の一括回復の1バイト目が[*]
具体的な指令と返却:
1、SET
client : SET MYTEST HELLO
MYTESTの値をHELLOに設定します.redisの通信プロトコルでは、コマンドをスペースで3行に分割し、最終的なコマンドは次のとおりです.
*3\r
-- 3
$3\r
-- “SET” 3
SET\r
$6\r
-- “MYTEST” 6
MYTEST\r
$5\r
-- “HELLO” 5
HELLO\r
server:サービス側操作成功:+OKrサービス側がエラーを返した場合:-エラー情報r
2、GET
client : GET MYTEST
生成された通信命令:
*2\r
$3\r
GET\r
$6\r
MYTEST
server:このkeyが存在する場合は、次を返します.
$5\r
HELLO\r
3、HKEYS
client : HKEYS MYTEST
以上のコマンドは、MYTESTに対応するfieldメンバーの数を取得します.
*2\r
$5\r
HKEYS\r
$6\r
MYTEST\r
server:フィールド情報が存在しない場合:*0r AGEフィールド情報が存在する場合:
*1\r
$2\r
AGE\r
4、HMGET
client :
HMGET MYTEST AGE
以上のコマンドは、HENRYのQQ情報を取得します.
*3\r
$5\r
HMGET\r
$6\r
MYTEST\r
$3\r
AGE\r
server :
フィールド値が存在しない場合
*1\r
$-1\r
フィールド値の存在
*1\r
$2\r
28\r
以上は主にRedisの一般的な処理のいくつかの情況を列挙して、指令が多すぎるため一つ一つ列挙しないで、もし自分でClientを実現する必要がある友达がRedisの公式に関連する命令のドキュメントを見ることができます.redis公式ドキュメント
練習ウィジェット:socketとredis serverで通信する
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.charset.Charset;
public class SimpleProtocol {
public static void main(String[] args) throws Exception{
Socket socket = new Socket();
socket.setReuseAddress(true);
// ,
socket.setKeepAlive(true);
// Nagle ,
socket.setTcpNoDelay(true);
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\
$3\\r\
SET\\r\
$9\\r\
simpleKey\\r\
$11\\r\
simpleValue\\r\
"));
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\
$3\\r\
GET\\r\
$9\\r\
simpleKey\\r\
"));
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 != '\
'){
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