资讯专栏INFORMATION COLUMN

Redis 通讯协议

weizx / 1538人阅读

摘要:命令发送格式参数数量参数的字节数量参数的数据参数的字节数量参数的数据其中表示举个例子格式化输出说明开头,表示有多少个参数,例如表示有个参数开头,表示参数的字节长度,例如表示有个字节,表示有个字节每行结尾通信协议为回复状态回复的第一个字节是,

redis命令发送格式:

*<参数数量> CRLF
$<参数 1 的字节数量> CRLF
<参数 1 的数据> CRLF
...
$<参数 N 的字节数量> CRLF
<参数 N 的数据> CRLF
其中CRLF表示 rn

举个例子:set name wuzhc
格式化输出:

*3
$3
set
$4
name
$5
wuzhc

说明:

*开头,表示有多少个参数,例如*3表示有3个参数(set, name, wuzhc)

$开头,表示参数的字节长度,例如$3表示set有3个字节,$4表示name有4个字节

每行rn结尾

通信协议为:
*3
$3
set
$4
name
$5
wuzhc
Redis 回复

状态回复(status reply)的第一个字节是 "+",例如+OK

错误回复(error reply)的第一个字节是 "-",例如-No such key

整数回复(integer reply)的第一个字节是 ":",例如:1

批量回复(bulk reply)的第一个字节是 "$",例如 $5 wuzhc

多条批量回复(multi bulk reply)的第一个字节是 "*",例如*2 $5 wuzhc $3r age

PHP 实现Redis客户端
_socket = stream_socket_client(
            "tcp://{$ip}:{$port}",
            $errno,
            $errstr,
            1,
            STREAM_CLIENT_CONNECT
        );
        if (!$this->_socket) {
            exit($errstr);
        }
    }

    /**
     * 执行redis命令
     * @param $command
     * @return array|bool|string
     */
    public function exec($command)
    {      
        // 拼装发送命令格式
        $command = $this->_execCommand($command);

        // 发送命令到redis
        fwrite($this->_socket, $command);

        // 解析redis响应内容
        return $this->_parseResponse();
    }

    /**
     * 将字符改为redis通讯协议格式
     * 例如mget name age 格式化为 *3
$4
mget
$4
name
$3
age

     * @param $command
     * @return bool|string
     */
    private function _execCommand($command)
    {
        $line = "";
        $crlf = "
";
        $params = explode(" ", $command);
        if (empty($params)) {
            return $line;
        }

        // 参数个数
        $line .= "*" . count($params) . $crlf;

        // 各个参数拼装
        foreach ((array)$params as $param) {
            $line .= "$" . mb_strlen($param, "8bit") . $crlf;
            $line .= $param . $crlf;
        }

        return $line;
    }

    /**
     * 解析redis回复
     * @return array|bool|string
     */
    private function _parseResponse()
    {
        $line = fgets($this->_socket); 
        $type = $line[0]; 
        $msg = mb_substr($line, 1, -2, "8bit"); 

        switch ($type) {
            // 状态回复
            case "+":
                if ($msg == "OK" || $msg == "PONG") {
                    return true;
                } else {
                    return $msg;
                }
            // 错误回复
            case "-":
                exit($msg);
            // 整数回复
            case ":":
                return $msg;
            // 批量回复
            case "$": // $后面跟数据字节数(长度)
                $line = fread($this->_socket, (int)$msg + 2); // 数据字节数 + (
)两个字节
                return mb_substr($line, 0, -2, "8bit"); // 去除最后两个字节
            // 多条批量回复
            case "*": // *表示后面有多少个参数
                $data = [];
                for ($i = 0; $i < $msg; $i++) {
                    $data[] = $this->_parseResponse();
                }
                return $data;
        }
    }
}

// demo
$client = new Client("127.0.0.1", 6379);
$client->exec("set name wuzhc");
$res = $client->exec("get name");
var_dump($res);

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/25823.html

相关文章

  • 用 Go 来了解一下 Redis 通讯协议

    摘要:用来了解一下通讯协议原文地址用来了解一下通讯协议都有那么多包来支撑你使用,那你是否有想过有了服务端,有了客户端,他们俩是怎样通讯,又是基于什么通讯协议做出交互的呢介绍基于我们的目的,本文主要讲解和实践的通讯协议的客户端和服务端是通过连接来进 用 Go 来了解一下 Redis 通讯协议 原文地址:用 Go 来了解一下 Redis 通讯协议 Go、PHP、Java... 都有那么多包来支...

    cnsworder 评论0 收藏0
  • PHP即时通讯设计实现

    摘要:即时通讯中,最重要的是响应速度,我们需要展示消息列表那么这时会有未读消息,未读数量,最后一条消息内容,时间等等。目前设计是单表单库。这里只是对即时通讯设计上做了一些简要的阐述,如有疑问和建议,请在评论区回复。 详解即时通讯设计实现(PHP+GatewayWorker+Redis) 需要实现的功能 一对一聊天(私聊) 一对多聊天(群聊) 类似QQ,微信等聊天列表 实时消息 显示 工具...

    asoren 评论0 收藏0
  • PHP即时通讯设计实现

    摘要:即时通讯中,最重要的是响应速度,我们需要展示消息列表那么这时会有未读消息,未读数量,最后一条消息内容,时间等等。目前设计是单表单库。这里只是对即时通讯设计上做了一些简要的阐述,如有疑问和建议,请在评论区回复。 详解即时通讯设计实现(PHP+GatewayWorker+Redis) 需要实现的功能 一对一聊天(私聊) 一对多聊天(群聊) 类似QQ,微信等聊天列表 实时消息 显示 工具...

    luckyyulin 评论0 收藏0

发表评论

0条评论

weizx

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<