服务是一个较抽象的概念,意在帮助使用者达到某种需求。那么对于网络服务来说,通常我们可以将其定义为一个运行在操作系统上的程序,使用者通过网络与其进行交互并得到想要的信息。

客户端和服务器通过TCP连接来进行数据交互,所以它和其它网络服务一样有一个协议。redis服务器接受命令以及命令的参数。服务器会在接到命令之后对命令进行处理,并将命令的回复传送到客户端。具体在网络层上就是:Redis在TCP端口6379上监听到来的连接,客户端连接到来时,Redis服务器为此创建一个TCP连接。在客户端与服务器端之间传输的每个Redis命令或者数据都以\r\n结尾。

redis的通讯协议包括:消息头标识和消息行,消息行里可能还有一个数据块大小的描述。redis是以行来划分的,每行以\r\n结束,且每一行都有一个消息头

消息体一共分为5种类型:

(1)[+]表示一个正确的状态信息,具体信息是:当前行+后面的字符
(2)[-]表示一个错误信息,具体信息是:当前行-后面的字符
(3)[]表示消息体总共有多少行,不包括当前行,后面是具体的行数
(4)[]表示下一行数据长度,不包括换行符\r\n的长度,]表示下一行数据长度,不包括换行符\r\n的长度,]表示下一行数据长度,不包括换行符\r\n的长度,后面则是对应长度的数据
(5)[:]表示返回一个数值,:后面是相应的数字字符

redis命令会返回多种不同类型的回复,通过检查服务器发回数据的第一个字节,可以确定这个回复是什么类型:

(1)状态回复的第一个字节是[+]
(2)错误回复的第一个字节是[-]
(3)整数回复的第一个字节是[:]
(4)批量回复的第一个字节是[$]
(5)多条批量回复的第一个字节是[*]

具体指令和返回:

1、SET

client : SET MYTEST HELLO

设置MYTEST的值为HELLO。
在redis的通讯协议上会以空格把命令拆分成三行,得到最终的命令如下:

*3\r\n     --消息体总共3行
$3\r\n     --下一行数据的长度“SET”为3
SET\r\n
$6\r\n     --下一行数据的长度“MYTEST”为6
MYTEST\r\n
$5\r\n     --下一行数据的长度“HELLO”为5
HELLO\r\n

server :
服务端操作成功:+OK\r\n
如果服务端返回错误: -错误信息\r\n

2、GET

client : GET MYTEST

产生的通讯指令:

*2\r\n
$3\r\n
GET\r\n
$6\r\n
MYTEST

server : 如果存在这个key则返回:

$5\r\n
HELLO\r\n

3、HKEYS

 client : HKEYS MYTEST

以上命令是获取对应MYTEST有多少个field成员:

*2\r\n
$5\r\n
HKEYS\r\n
$6\r\n
MYTEST\r\n

server :
如果不存在任何字段信息:*0\r\n
如果存在一个AGE字段信息:

*1\r\n
$2\r\n
AGE\r\n

4、HMGET

client :
HMGET MYTEST AGE

以上命令是获取HENRY的QQ信息。

*3\r\n
$5\r\n
HMGET\r\n
$6\r\n
MYTEST\r\n
$3\r\n
AGE\r\n

server :

如果不存在字段值

*1\r\n
$-1\r\n

存在字段值

*1\r\n
$2\r\n
28\r\n

以上主要列举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);//连接serversocket.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();}//CRis.read();//LFis.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 : OKresponse type is : $$ value len : 11GET command response : simpleValue

【Redis学习】redis通讯协议相关推荐

  1. Redis和MongoDB通讯协议简介

    为什么80%的码农都做不了架构师?>>>    Redis Redis的通讯协议可以说大集汇了--消息头标识,消息行还有就行里可能还有个数据块大小描述.首先Redis是以行来划分,每 ...

  2. Redis 学习---Redis 安装(2)

    Redis 安装 Window 下安装 下载地址:https://github.com/MSOpenTech/redis/releases. Redis 支持 32 位和 64 位.这个需要根据你系统 ...

  3. redis学习-redis入门概述及简介

    是什么 Redis:REmote DIctionary Server(远程字典服务器)是完全开源免费的,用C语言编写的,遵守BSD协议,是一个高性能的(key/value)分布式内存数据库,基于内存运 ...

  4. redis学习-redis事务

    是什么 可以一次执行多个命令,本质是一组命令的集合.一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞. 一次执行多个redis命令. 能干嘛 一个队列中,一次性.顺序性 ...

  5. redis学习-redis五大数据类型

    五大数据类型简介 String(字符串) string是redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value. 也就是例子中的k1 v1,k2 v2 s ...

  6. Redis学习---Redis操作之String

    set(name, value, ex=None, px=None, nx=False, xx=False) 在Redis中设置值,默认,不存在则创建,存在则修改 参数: ex,过期时间(秒) px, ...

  7. redis学习——redis事务

    Redis事务的概念: Redis 事务的本质是一组命令的集合.事务支持一次执行多个命令,一个事务中所有命令都会被序列化.在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会 ...

  8. Redis学习:基本知识点(转载)

    转载于:https://mp.weixin.qq.com/s/lsOYc2pxXo1vYs8_E0R3uQ 本篇文章仅供于个人的学习和记录 1.基本类型及底层实现 1.1.String 用途: 适用于 ...

  9. Redis通讯协议RESP详解

    Redis的作者认为数据库系统的瓶颈一般不在于网络流量,而是数据库自身内部逻辑处理上.所以即使Redis使用了浪费流量的文本协议,依然可以取得极高的访问性能.Redis将所有数据都放在内存,用一个单线 ...

最新文章

  1. 【C++】operator bool() 和 operator const bool() const
  2. 2017年9月19日
  3. ctype_digit()函数
  4. MapReduce 计数器简介(转载自:http://www.tuicool.com/articles/qqyIBr)
  5. android 自定义view实现拖动放大缩小_自定义itemCheckView
  6. Firefox for iOS现身Github 使用Swift编写
  7. python 程序bug解决方案
  8. 电脑主机启动不了是什么原因
  9. RESTful API 设计思考
  10. Matlab 谢尔宾斯基三角形
  11. 30【源码】数据可视化大屏:基于 Echarts + Python Flask 实现的32-9超宽大屏 - 中国国际疫情实时追踪
  12. 贪心科技机器学习训练营(十二)
  13. ET1100和PHY的总结
  14. 集合的特性(成员操作符、for循环遍历)
  15. 优思学院|六西格玛管理的经典六步法
  16. Android开发之视频播放器
  17. 用于2D动画的实时嘴型同步技术
  18. 前端 下载文件简易方法(兼容IE)
  19. 【jquery】jquery $.fn $.fx是什么意思
  20. 自闭症的白质微观结构研究

热门文章

  1. 一个应用程序多线程误用的分析
  2. Linux环境用Sendmail架设Mail服务器
  3. [转]使用Yii CUploadedFile上传文件(图片)
  4. 通过CMOS设置定时开机
  5. Directory Service Maintenance
  6. Android之drawable state各个属性详解
  7. Eclipse 中 按 Ctrl+Shift+F 格式化代码时每行容纳的字符数
  8. TortoiseSVN Unable to connect to a repository at URL XXX
  9. listview异步加载图片
  10. Android---AlertDialog