*<參數數量> CRLF
$<參數 1 的字節數量> CRLF
<參數 1 的數據> CRLF
...
$<參數 N 的字節數量> CRLF
<參數 N 的數據> CRLF
其中CRLF表示 rnphp
*3
$3
set
$4
name
$5
wuzhcredis
*開頭,表示有多少個參數,例如*3表示有3個參數(set, name, wuzhc)bash
$開頭,表示參數的字節長度,例如$3表示set有3個字節,$4表示name有4個字節socket
每行rn結尾tcp
*3\r\n$3\r\nset\r\n$4\r\nname\r\n$5\r\nwuzhc\r\n
狀態回覆(status reply)的第一個字節是 "+",例如+OK\r\nthis
錯誤回覆(error reply)的第一個字節是 "-",例如-No such key\r\ncode
整數回覆(integer reply)的第一個字節是 ":",例如:1\r\norm
批量回復(bulk reply)的第一個字節是 "$",例如 $5\r\nwuzhc\r\nip
多條批量回復(multi bulk reply)的第一個字節是 "*",例如*2\r\n$5\r\nwuzhc\r\n$3r\nage\r\nget
<?php /** * Created by PhpStorm. * User: wuzhc2016@163.com * Date: 2017年09月12日 * Time: 9:08 */ class Client { private $_socket = null; public function __construct($ip, $port) { $this->_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\r\n$4\r\nmget\r\n$4\r\nname\r\n$3\r\nage\r\n * @param $command * @return bool|string */ private function _execCommand($command) { $line = ''; $crlf = "\r\n"; $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); // 數據字節數 + (\r\n)兩個字節 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);