资讯专栏INFORMATION COLUMN

swoole——从入门到放弃(一)

morgan / 3599人阅读

摘要:进程可以使用函数向进程投递新的任务。当前的进程在调用回调函数时会将进程状态切换为忙碌,这时将不再接收新的,当函数返回时会将进程状态切换为空闲然后继续接收新的。当进程投递的任务在中完成时,进程会通过方法将任务处理的结果发送给进程。

swoole——从入门到放弃(一) 一、swoole的源码包安装

下载swoole源码:git clone https://gitee.com/swoole/swoole.git

通过phpize(扩展php扩展模块,建立php外挂模块):

cd swoole

执行:your/phpize/path

./configure --with-php-config=your/php/path/bin/php-config

make && make install

可以看到swoole.so的位置

我的位置是:/opt/soft/php/lib/php/extensions/no-debug-non-zts-20170718/

配置php.ini

添加extension=swoole.so

通过php -m命令,可以看到php的扩展模块

检测swoole安装成功并且php支持swoole

cd your/swoole/path/examples/server

php echo.php(如果进程被阻塞,则说明成功)

netstat -anp | grep 9501(查看swoole开启的端口号)


二、网络通信引擎
学习swoole需要去翻阅文档,swoole文档
1.通过swoole创建一个最简单的tcp服务
tcp服务端(tcp_server.php)
//创建Server对象,监听 127.0.0.1:9501端口
$serv = new swoole_server("127.0.0.1", 9501);

$serv->set([
    "worker_num" => 4, // worker进程数,cpu 1-4倍
    "max_request" => 100,
]);

/**
 * 监听连接进入事件
 * $fd 客户端连接服务端的唯一标识
 * $reactor_id 线程id
 */
$serv->on("connect", function ($serv, $fd, $reactor_id) {
    echo "Client: {$fd} - {$reactor_id} - Connect.
";
});

//监听数据接收事件
$serv->on("receive", function ($serv, $fd, $reactor_id, $data) {
    $serv->send($fd, "Server: ".$data);
});

//监听连接关闭事件
$serv->on("close", function ($serv, $fd) {
    echo "Client: Close.
";
});

//启动服务器
$serv->start();
tcp客户端(tcp_client.php)
// 创建tcp客户端
$client = new swoole_client(SWOOLE_SOCK_TCP);

// 连接tcp服务端
if (!$client->connect("127.0.0.1", 9501)) {
    echo "连接失败";
    exit;
}

// php cli
fwrite(STDOUT, "请输入:");
$msg = trim(fgets(STDIN));

// 发送消息给tcp服务端
if (!$client->send($msg)) {
    echo "发送消息失败";
    exit;
}

// 接收
$result = $client->recv();
echo $result;
2.拓展:php的四种回调

匿名函数

$server->on("Request", function ($req, $resp) {
    echo "hello world";
});

类静态方法

class A
{
    static function test($req, $resp)
    {
        echo "hello world";
    }
}
$server->on("Request", "A::Test");
$server->on("Request", array("A", "Test"));

函数

function my_onRequest($req, $resp)
{
    echo "hello world";
}
$server->on("Request", "my_onRequest");

对象方法

class A
{
    function test($req, $resp)
    {
        echo "hello world";
    }
}

$object = new A();
$server->on("Request", array($object, "test"));
小技巧:查看开启的worker进程:ps aft | grep tcp_server.php

3. udp的服务端和客户端可以根据文档自行创建
4. http服务
// 监听所有地址和9501端口
$http = new swoole_http_server("0.0.0.0", 9501);

// 动静分离配置
$http->set([
    // 开启静态请求
    "enable_static_handler" => true,
    // 静态资源目录
    "document_root" => "/opt/app/code1/",
]);

$http->on("request", function ($request, $response) {
    // 获取get请求的参数
    $param = json_encode($request->get);
    // 设置cookie
    $response->cookie("name", "ronaldo", time() + 1800);
    // 输出到页面
    $response->end("

Hello Swoole - {$param}

"); }); // 开启http服务 $http->start();

5.通过swoole创建websocket服务
websocket服务端(websocket_server.php)
// 监听所有地址和9502端口
$server = new swoole_websocket_server("0.0.0.0", 9502);

// 动静分离配置
$server->set([
    // 开启静态请求
    "enable_static_handler" => true,
    // 静态资源目录
    "document_root" => "/opt/app/swoole/websocket",
]);
$server->on("open", function ($server, $request) {
    echo "server:handshake success with fd - {$request->fd}
";
});

$server->on("message", function ($server, $frame) {
    echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}
";
    $server->push($frame->fd, "this is server");
});

$server->on("close", function ($server, $fd) {
    echo "client - {$fd} - close
";
});

$server->start();
websocket客户端 (websockt_client.html)
// 创建websocket实例
        var websocketURL = "ws://www.rona1do.top:9502";
        var websocket = new WebSocket(websocketURL);

        // 实例化对象的onopen属性
        websocket.onopen = function (ev) {
            websocket.send("hello-websocket");
            console.log("connect-swoole-success");
        }

        // 实例化对象的onmessage属性,接收服务端返回的数据
        websocket.onmessage = function (ev) {
            console.log("websockect-server-return-data:" + ev.data);
        }

        // close
        websocket.onclose = function (ev) {
            console.log("close");
        }

6. 使用面向对象来优化websocket服务代码
class WebSocket {
    const HOST = "0.0.0.0";
    const PORT = 9502;

    private $ws = null;

    function __construct()
    {
        $this->ws = new swoole_websocket_server(self::HOST, self::PORT);
        $this->ws->on("open", [$this, "onOpen"]);
        $this->ws->on("message", [$this, "onMessage"]);
        $this->ws->on("close", [$this, "onClose"]);
        $this->ws->start();
    }

    // 监听websocket连接事件
    function onOpen($server, $request) {
        echo "server: handshake success with fd{$request->fd}
";
    }

    // 监听websocket消息接收事件
    function onMessage($server, $frame) {
        echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}
";
        $server->push($frame->fd, "this is server");
    }

    // 监听客户端关闭事件
    function onClose($server, $fd) {
        echo "Client:{$fd} closes
";
    }
}

7.swoole中的task小案例
onTask:在task_worker进程内被调用。worker进程可以使用swoole_server_task函数向task_worker进程投递新的任务。当前的Task进程在调用onTask回调函数时会将进程状态切换为忙碌,这时将不再接收新的Task,当onTask函数返回时会将进程状态切换为空闲然后继续接收新的Task。
onFinish:当worker进程投递的任务在task_worker中完成时,task进程会通过swoole_server->finish()方法将任务处理的结果发送给worker进程。
class Websocket {

    const HOST = "0.0.0.0";
    const PORT = 9502;
    private $ws = null;

    public function __construct()
    {
        $this->ws = new swoole_websocket_server(self::HOST, self::PORT);
        $this->ws->set([
            "worker_num" => 2,
            "task_worker_num" => 2, // 要想使用task必须要指明
        ]);
        $this->ws->on("open", [$this, "onOpen"]);
        $this->ws->on("message", [$this, "onMessage"]);
        $this->ws->on("task", [$this, "onTask"]);
        $this->ws->on("finish", [$this, "onFinish"]);
        $this->ws->on("close", [$this, "onClose"]);
        $this->ws->start();
    }

    public function onOpen($server, $request)
    {
        echo "server:handshake success with fd:{$request->fd}
";
    }

    public function onMessage($server, $frame)
    {
        echo "receive from {$frame->fd}:{$frame->data}
";

        // 需要投递的任务数据
        $data = [
            "fd" => $frame->fd,
            "msg" => "task",
        ];
        $server->task($data);

        $server->push($frame->fd, "this is server");
    }

    // 处理投递的任务方法,非阻塞
    public function onTask($server, $task_id, $worker_id, $data)
    {
        print_r($data);
        // 模拟大量数据的操作
        sleep(10);
        return "task_finish";
    }
    
    // 投递任务处理完毕调用的方法
    public function onFinish($server, $task_id, $data)
    {
        echo "task_id:{$task_id}
";
        echo "task finish success:{$data}
";
    }
    
    public function onClose($server, $fd)
    {
        echo "Client:close";
    }
}

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

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

相关文章

  • swoole——入门放弃(三)

    摘要:从入门到放弃三一进程子进程创建成功后要执行的函数重定向子进程的标准输入和输出。默认为阻塞读取。是否创建管道,启用后,此选项将忽略用户参数,强制为。 swoole——从入门到放弃(三) 一、进程 swoole_process SwooleProcess swoole_process::__construct(callable $function, $redirect_stdin...

    王笑朝 评论0 收藏0
  • swoole——入门放弃(三)

    摘要:从入门到放弃三一进程子进程创建成功后要执行的函数重定向子进程的标准输入和输出。默认为阻塞读取。是否创建管道,启用后,此选项将忽略用户参数,强制为。 swoole——从入门到放弃(三) 一、进程 swoole_process SwooleProcess swoole_process::__construct(callable $function, $redirect_stdin...

    rottengeek 评论0 收藏0
  • swoole——入门放弃(二)

    摘要:从入门到放弃二一异步毫秒定时器设置一个间隔时钟定时器,与定时器不同的是定时器会持续触发,直到调用清除。是一次性函数,执行完成后就会销毁最大不超过使用定时器来删除定时器。 swoole——从入门到放弃(二) 一、异步毫秒定时器 swoole_timer_tick:设置一个间隔时钟定时器,与after定时器不同的是tick定时器会持续触发,直到调用swoole_timer_clear清...

    awokezhou 评论0 收藏0
  • swoole——入门放弃(二)

    摘要:从入门到放弃二一异步毫秒定时器设置一个间隔时钟定时器,与定时器不同的是定时器会持续触发,直到调用清除。是一次性函数,执行完成后就会销毁最大不超过使用定时器来删除定时器。 swoole——从入门到放弃(二) 一、异步毫秒定时器 swoole_timer_tick:设置一个间隔时钟定时器,与after定时器不同的是tick定时器会持续触发,直到调用swoole_timer_clear清...

    tinyq 评论0 收藏0

发表评论

0条评论

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