溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

swoole的示例分析

發(fā)布時(shí)間:2020-12-19 13:59:14 來源:億速云 閱讀:245 作者:小新 欄目:編程語言

小編給大家分享一下swoole的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

一、swoole的源碼包安裝

  1. 下載swoole源碼:git clone https://gitee.com/swoole/swoole.git

  2. 通過phpize(擴(kuò)展php擴(kuò)展模塊,建立php外掛模塊):

    • cd swoole

    • 執(zhí)行:your/phpize/path

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

    • make && make install

  3. 可以看到swoole.so的位置

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

  4. 配置php.ini

    • 添加extension=swoole.so

  5. 通過php -m命令,可以看到php的擴(kuò)展模塊

  6. 檢測swoole安裝成功并且php支持swoole

    • cd your/swoole/path/examples/server

    • php echo.php(如果進(jìn)程被阻塞,則說明成功)

    • netstat -anp | grep 9501(查看swoole開啟的端口號)


二、網(wǎng)絡(luò)通信引擎

學(xué)習(xí)swoole需要去翻閱文檔,  swoole文檔

1.通過swoole創(chuàng)建一個(gè)最簡單的tcp服務(wù)

tcp服務(wù)端(tcp_server.php)
//創(chuàng)建Server對象,監(jiān)聽 127.0.0.1:9501端口
$serv = new swoole_server("127.0.0.1", 9501);

$serv->set([
    'worker_num' => 4, // worker進(jìn)程數(shù),cpu 1-4倍
    'max_request' => 100,
]);

/**
 * 監(jiān)聽連接進(jìn)入事件
 * $fd 客戶端連接服務(wù)端的唯一標(biāo)識
 * $reactor_id 線程id
 */
$serv->on('connect', function ($serv, $fd, $reactor_id) {
    echo "Client: {$fd} - {$reactor_id} - Connect.\n";
});

//監(jiān)聽數(shù)據(jù)接收事件
$serv->on('receive', function ($serv, $fd, $reactor_id, $data) {
    $serv->send($fd, "Server: ".$data);
});

//監(jiān)聽連接關(guān)閉事件
$serv->on('close', function ($serv, $fd) {
    echo "Client: Close.\n";
});

//啟動服務(wù)器
$serv->start();
tcp客戶端(tcp_client.php)
// 創(chuàng)建tcp客戶端
$client = new swoole_client(SWOOLE_SOCK_TCP);

// 連接tcp服務(wù)端
if (!$client->connect("127.0.0.1", 9501)) {
    echo '連接失敗';
    exit;
}

// php cli
fwrite(STDOUT, '請輸入:');
$msg = trim(fgets(STDIN));

// 發(fā)送消息給tcp服務(wù)端
if (!$client->send($msg)) {
    echo '發(fā)送消息失敗';
    exit;
}

// 接收
$result = $client->recv();
echo $result;

2.拓展:php的四種回調(diào)

  • 匿名函數(shù)

$server->on('Request', function ($req, $resp) {
    echo "hello world";
});
  • 類靜態(tài)方法

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

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進(jìn)程:  ps aft | grep tcp_server.php

3. udp的服務(wù)端和客戶端可以根據(jù)文檔自行創(chuàng)建


4. http服務(wù)

// 監(jiān)聽所有地址和9501端口
$http = new swoole_http_server('0.0.0.0', 9501);

// 動靜分離配置
$http->set([
    // 開啟靜態(tài)請求
    'enable_static_handler' => true,
    // 靜態(tài)資源目錄
    'document_root' => '/opt/app/code1/',
]);

$http->on('request', function ($request, $response) {
    // 獲取get請求的參數(shù)
    $param = json_encode($request->get);
    // 設(shè)置cookie
    $response->cookie('name', 'ronaldo', time() + 1800);
    // 輸出到頁面
    $response->end("<h2>Hello Swoole - {$param}</h2>");
});

// 開啟http服務(wù)
$http->start();

5.通過swoole創(chuàng)建websocket服務(wù)

websocket服務(wù)端(websocket_server.php)
// 監(jiān)聽所有地址和9502端口
$server = new swoole_websocket_server('0.0.0.0', 9502);

// 動靜分離配置
$server->set([
    // 開啟靜態(tài)請求
    'enable_static_handler' => true,
    // 靜態(tài)資源目錄
    'document_root' => '/opt/app/swoole/websocket',
]);
$server->on('open', function ($server, $request) {
    echo "server:handshake success with fd - {$request->fd}\n";
});

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

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

$server->start();
websocket客戶端 (websockt_client.html)
// 創(chuàng)建websocket實(shí)例
        var websocketURL = "ws://www.rona1do.top:9502";
        var websocket = new WebSocket(websocketURL);

        // 實(shí)例化對象的onopen屬性
        websocket.onopen = function (ev) {
            websocket.send("hello-websocket");
            console.log("connect-swoole-success");
        }

        // 實(shí)例化對象的onmessage屬性,接收服務(wù)端返回的數(shù)據(jù)
        websocket.onmessage = function (ev) {
            console.log("websockect-server-return-data:" + ev.data);
        }

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

6. 使用面向?qū)ο髞韮?yōu)化websocket服務(wù)代碼

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();
    }

    // 監(jiān)聽websocket連接事件
    function onOpen($server, $request) {
        echo "server: handshake success with fd{$request->fd}\n";
    }

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

    // 監(jiān)聽客戶端關(guān)閉事件
    function onClose($server, $fd) {
        echo "Client:{$fd} closes\n";
    }
}

7.swoole中的task小案例

onTask:在task_worker進(jìn)程內(nèi)被調(diào)用。worker進(jìn)程可以使用swoole_server_task函數(shù)向task_worker進(jìn)程投遞新的任務(wù)。當(dāng)前的Task進(jìn)程在調(diào)用onTask回調(diào)函數(shù)時(shí)會將進(jìn)程狀態(tài)切換為忙碌,這時(shí)將不再接收新的Task,當(dāng)onTask函數(shù)返回時(shí)會將進(jìn)程狀態(tài)切換為空閑然后繼續(xù)接收新的Task。
onFinish:當(dāng)worker進(jìn)程投遞的任務(wù)在task_worker中完成時(shí),task進(jìn)程會通過swoole_server->finish()方法將任務(wù)處理的結(jié)果發(fā)送給worker進(jìn)程。
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}\n";
    }

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

        // 需要投遞的任務(wù)數(shù)據(jù)
        $data = [
            'fd' => $frame->fd,
            'msg' => 'task',
        ];
        $server->task($data);

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

    // 處理投遞的任務(wù)方法,非阻塞
    public function onTask($server, $task_id, $worker_id, $data)
    {
        print_r($data);
        // 模擬大量數(shù)據(jù)的操作
        sleep(10);
        return "task_finish";
    }
    
    // 投遞任務(wù)處理完畢調(diào)用的方法
    public function onFinish($server, $task_id, $data)
    {
        echo "task_id:{$task_id}\n";
        echo "task finish success:{$data}\n";
    }
    
    public function onClose($server, $fd)
    {
        echo "Client:close";
    }
}

以上是“swoole的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI