redis通信协议
Redis跟据不同的命令进行不同的回复。redis server回复的内容类型通过第一个参数可以判断:
1."+"号开头表示单行字符串的回复 如:+OK
2."-"号开头表示错误的信息回复。 如:-wrong date type
3.":"号开头表示一个整数回复。 如":0\r\n"
4."$"号开头表示一个批量的回复。 如GET mykey 返回$6\r\nfoobar\r\n 其中6为字节数,foobar为实现的字符串数据。
5."*"号开头表示多个批量回复。
在这个新的协议中,所有的发送到redis-server的参数都是二进制安全的,其基本形式如下:
*<参数的个数> CR LF
$<参数1字节数> CR LF
<参数1> CR LF
...
$<参数n字节数> CR LF
<参数n> CR LF
例如命令:set mykey myvalue 相对应的形式应该如下,
*3 CR LF //三个参数
$3 CR LF //第一个参数set有三个字节
SET CR LF //参数内容set
$5 CR LF //第二个参数mykey有五个字节
mykey CR LF //参数二内容 mykey
$7 CR LF //第三个参数有7个字节
myvalue CR LF //参数三内容 myvalue
字符串形式的结果就是 : "*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nmyvalue\r\n"
RedisServer关键代码
$socket = fsockopen($host, $port, $errno, $errstr);
if (!$socket)
{
$this->reportError('Connection error: '.$errno.':'.$errstr);
return false;
}
$this->connection = $socket;
protected function _send($args)
{
$command = '*'.count($args)."\r\n";
foreach ($args as $arg) $command .= "$".strlen($arg)."\r\n".$arg."\r\n";
$w = fwrite($this->connection, $command);
$answer = $this->_read_reply();
if ($answer===false && $this->repeat_reconnected)
{
if (fwrite($this->connection, $command))
{
$answer = $this->_read_reply();
}
$this->repeat_reconnected = false;
}
return $answer;
}3)解析内容
protected function _read_reply()
{
$server_reply = fgets($this->connection);
if ($server_reply===false)
{
if (!$this->connect($this->host, $this->port))
{
return false;
}
else
{
$server_reply = fgets($this->connection);
if (empty($server_reply))
{
$this->repeat_reconnected = true;
return false;
}
}
}
$reply = trim($server_reply);
$response = null;
switch ($reply[0])
{
/* Error reply */
case '-':
$this->reportError('error: '.$reply);
return false;
/* Inline reply */
case '+':
return substr($reply, 1);
/* Bulk reply */
case '$':
if ($reply=='$-1') return null;
$response = null;
$size = intval(substr($reply, 1));
if ($size > 0)
{
$response = stream_get_contents($this->connection, $size);
}
fread($this->connection, 2); /* discard crlf */
break;
/* Multi-bulk reply */
case '*':
$count = substr($reply, 1);
if ($count=='-1') return null;
$response = array();
for ($i = 0; $i < $count; $i++)
{
$response[] = $this->_read_reply();
}
break;
/* Integer reply */
case ':':
return intval(substr($reply, 1));
break;
default:
$this->reportError('Non-protocol answer: '.print_r($server_reply, 1));
return false;
}
return $response;
}

637

被折叠的 条评论
为什么被折叠?



