php实现redis的服务端的示例

大家都知道redis是用C来实现的,现在我用php来实现一个简单的仅支持SET和GET命令的redis服务端,主要是为了更好的了解redis的服务端和php的网络编程.

代码如下:

<?php
/**
 * 多进程阻塞式
 */
class Xtgxiso_server
{
    private $socket = false;
    private $process_num = 100;
    public $redis_kv_data = array();
    public $onMessage = null;

    function __construct($host="0.0.0.0",$port=1215)
    {
        $this->socket = stream_socket_server("tcp://".$host.":".$port,$errno, $errstr);
        if (!$this->socket) die($errstr."--".$errno);
        echo "listen $host $port \r\n";
        ini_set("memory_limit", "128M");
    }

    private function parseRESP(&$conn){
        $line = fgets($conn);
        if($line === '' || $line === false)
        {
            return null;
        }
        $type = $line[0];
        $line = mb_substr($line,1,-2);
        switch ( $type ){
            case "*":
                $count = (int) $line;
                $data = array();
                for ($i = 1; $i <= $count; $i++) {
                    $data[] = $this->parseRESP($conn);
                }
                return $data;
            case "$":
                if ($line == '-1') {
                    return null;
                }
                $length = $line + 2;
                $data = '';
                while ($length > 0) {
                    $block = fread($conn, $length);
                    if ($length !== strlen($block)) {
                        throw new Exception('RECEIVING');
                    }
                    $data .= $block;
                    $length -= mb_strlen($block);
                }
                return mb_substr($data, 0, -2);
        }
        return $line;
    }

    private function start_worker_process(){
        $pid = pcntl_fork();
        switch ($pid) {
            case -1:
                echo "fork error : {$i} \r\n";
                exit;
            case 0:
                while ( 1 ) {
                    echo  "waiting...\n";
                    $conn = stream_socket_accept($this->socket, -1);
                    if ( !$conn ){
                        continue;
                    }
                    //"*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nmyvalue\r\n"
                    while(1){
                        $arr = $this->parseRESP($conn);
                        if ( is_array($arr) ) {
                            if ($this->onMessage) {
                                call_user_func($this->onMessage, $conn, $arr);
                            }
                        }else if ( $arr ){
                            if ($this->onMessage) {
                                call_user_func($this->onMessage, $conn, $arr);
                            }
                        }else{
                            fclose($conn);
                            break;
                        }
                    }
                }
            default:
                $this->pids[$pid] = $pid;
                break;
        }
    }

    public function run(){
        for($i = 1; $i <= $this->process_num; $i++){
            $this->start_worker_process();
        }

        while(1){
            foreach ($this->pids as $i => $pid) {
                if($pid) {
                    $res = pcntl_waitpid($pid, $status,WNOHANG);

                    if ( $res == -1 || $res > 0 ){
                        $this->start_worker_process();
                        unset($this->pids[$pid]);
                    }
                }
            }
            sleep(1);
        }
    }

}
$server =  new Xtgxiso_server();

$server->onMessage = function($conn,$info) use($server){
    if ( is_array($info) ){
        if ( $info["0"] == "SET" ) {
            $key = $info[1];
            $val = $info[2];
            $server->redis_kv_data[$key] = $val;
            fwrite($conn, "+OK\r\n");
        }else if ( $info["0"] == "GET" ){
            $key = $info[1];
            fwrite($conn, "$".strlen($server->redis_kv_data[$key])."\r\n".$server->redis_kv_data[$key]."\r\n");
        }else{
            fwrite($conn,"+OK\r\n");
        }
    }else{
        fwrite($conn,"+OK\r\n");
    }
};

$server->run();
通过如下命令来测试PHP实现的性能:

redis-benchmark -h 10.170.233.221 -p 1215 -t set -n 80000 -q


 

看来还是不错的,大家有兴趣可以再实现其他命令!

时间: 2024-09-24 08:18:24

php实现redis的服务端的示例的相关文章

udp socket客户端和udp服务端程序示例分享_C 语言

Udp Socket 复制代码 代码如下: #include <WinSock2.h>#include <stdio.h>#pragma comment(lib, "ws2_32.lib")int main(){// initial socket libraryWORD wVerisonRequested;WSADATA wsaData;int err;wVerisonRequested = MAKEWORD(1, 1);err = WSAStartup(wVe

服务端 VBScript 与 JScript 几个相同特性的写法与示例_应用技巧

By shawl.qiu 摘要: 本文演示了ASP服务端脚本的几个重要应用.  目录: 1. 遍历集合/对象 1.1 VBScript 遍历表单集合 1.2 JScript 遍历表单集合 2. 转变量值为变量, 并赋值 2.1 VBScript 转变量值为变量并赋值 2.2 JScript 转变量值为变量并赋值 3. 动态包含文件 3.1 VBScript 动态包含文件 3.2 JScript 动态包含文件 shawl.qiu 2006-10-11 http://blog.csdn.net/bt

js跨域访问示例(客户端/服务端)_javascript技巧

复制代码 代码如下: <div id="oid"></div> <script type="text/javascript"> //获取货号 $.ajax({ url: "http://192.168.1.191/H.ashx", type: "GET", dataType: 'jsonp', //jsonp的值自定义,如果使用jsoncallback,那么服务器端,要返回一个jsoncal

python网络编程示例(客户端与服务端)_python

client客户端 复制代码 代码如下: if __name__ == '__main__':       import socket       import os    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)       sock.connect(('localhost', 8001))       import time       time.sleep(2)       sock.send('1')       p

简单的java socket客户端和服务端示例_java

客户端 复制代码 代码如下: import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.Socket; public class MyClient {      public static void main(String[] args) throws Exception {          Socket socket = new Socke

golang实现简单的udp协议服务端与客户端示例_Golang

本文实例讲述了golang实现简单的udp协议服务端与客户端.分享给大家供大家参考,具体如下: 其实udp没有什么服务端和客户端的概念了,只是一个发一个收而已,只是这样较方便能识别和理解. 服务端: 复制代码 代码如下: package main import (     "fmt"     "net" ) func main() {     // 创建监听     socket, err := net.ListenUDP("udp4", &am

JQuery以JSON方式提交数据到服务端示例代码_jquery

JQuery将Ajax数据请求进行了封装,从而使得该操作实现起来容易许多.以往我们要写很多的代码来实现该功能,现在只需要调用$.ajax()方法,并指明请求的方式.地址.数据类型,以及回调方法等.下面的代码演示了如何将客户端表单数据封装成JSON格式,然后通过JQuery的Ajax请求将数据发送到服务端,并最终将数据存储到数据库中.服务端定义为一个.ashx文件,事实上你可以将服务端定义为任何能接收并处理客户端数据的类型,如Web Service,ASP.NET Page,Handler等. 首

asp.net代码部署与服务端获取数据示例

我准备写一个ztree使用系列的教程基于asp.net的,希望能坚持下去. 本教程基于一个city.xml的全国数据文件,大家可以到这里下载. 1.Ztree介绍   zTree 是一个依靠 jQuery 实现的多功能 "树插件".优异的性能.灵活的配置.多种功能的组合是 zTree 最大优点.     zTree 是开源免费的软件(MIT 许可证).如果您对 zTree 感兴趣或者愿意资助 zTree 继续发展下去,可以进行捐助. zTree v3.0 将核心代码按照功能进行了分割,

tcp socket客户端和服务端示例分享_C 语言

以下是tcp socket客户端和服务端源码,代码简单大家参考使用吧 Tcp Server 复制代码 代码如下: #include <WinSock2.h>#include <stdio.h>#pragma comment(lib, "ws2_32.lib")int main(){// initial socket libraryWORD wVerisonRequested;WSADATA wsaData;int err;wVerisonRequested =