国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

??
推薦(免費):Swoole框架" >推薦(免費):Swoole框架
前言
安裝
基于TCP的郵件服務(wù)器
基于WebSocket多房間聊天功能
基于HTTP的簡易框架
總結(jié)
? PHP ????? Swoole Swoole? ??? ?? ??? ?????.

Swoole? ??? ?? ??? ?????.

Dec 11, 2020 pm 05:43 PM
swoole

Swoole框架欄目介紹介紹Swoole的簡單運用實現(xiàn)例子

Swoole? ??? ?? ??? ?????.

推薦(免費):Swoole框架

前言

我們使用PHP開發(fā)WEB應(yīng)用基本都是使用傳統(tǒng)的LAMP/LNMP模式來提供HTTP服務(wù),這種模式一般是同步且堵塞的,若我們想使用PHP開發(fā)一些高級的特性(例如:異步,非堵塞,網(wǎng)絡(luò)服務(wù)器等),那么Swoole無疑是最佳的選擇,那什么是Swoole呢?

PHP的異步、并行、高性能網(wǎng)絡(luò)通信引擎,使用純C語言編寫,提供了 PHP語言的異步多線程服務(wù)器, 異步TCP/UDP網(wǎng)絡(luò)客戶端, 異步MySQL, 異步Redis, 數(shù)據(jù)庫連接池, AsyncTask, 消息隊列, 毫秒定時器, 異步文件讀寫, 異步DNS查詢。 Swoole內(nèi)置了 Http/WebSocket服務(wù)器端/ 客戶端、 Http2.0服務(wù)器端/ 客戶端。

簡單的來說,Swoole是一個PHP擴展,實現(xiàn)了網(wǎng)絡(luò)層的很多功能,應(yīng)用場景非常廣,下面列舉幾個例子簡單介紹一下Swoole的應(yīng)用。

安裝

按照官方文檔進行安裝:Swoole官網(wǎng),安裝完后使用命令:

php -m

查看是否安裝成功。注意:Swoole從2.0版本開始支持了內(nèi)置協(xié)程,需使用PHP7。

基于TCP的郵件服務(wù)器

使用Swoole提供TCP服務(wù),異步任務(wù)發(fā)送郵件。

郵件功能:

PHPMailer

PHP主代碼:

<?php

$object = new MailServer();

$setting = [
    &#39;log_file&#39; => &#39;swoole.log&#39;,
    &#39;worker_num&#39; => 4, // 4個工作進程
    &#39;task_worker_num&#39; => 10, // 10個任務(wù)進程
];
$server = new swoole_server("127.0.0.1", 9501);
$server->set($setting);

$server->on(&#39;WorkerStart&#39;, array($object, &#39;onWorkerStart&#39;));
$server->on(&#39;Connect&#39;, array($object, &#39;onConnect&#39;));
$server->on(&#39;Receive&#39;, array($object, &#39;onReceive&#39;));
$server->on(&#39;Close&#39;, array($object, &#39;onClose&#39;));
$server->on(&#39;Task&#39;, array($object, &#39;onTask&#39;));
$server->on(&#39;Finish&#39;, array($object, &#39;onFinish&#39;));

$server->start();

class MailServer
{
    /** @var Mail */
    private $handle;

    public function __construct()
    {
        require &#39;Mail.php&#39;; // PHPMailer郵件服務(wù)類
    }

    public function onWorkerStart($server, $workerId)
    {
        $mailConfig = require &#39;MailConfig.php&#39;; // 發(fā)件人信息,重啟時會重新加載配置文件
        $this->handle = new Mail($mailConfig);
    }

    public function onConnect($server, $fd, $reactorId)
    {

    }

    public function onReceive($server, $fd, $reactorId, $data)
    {
        $return = [];
        $dataArr = json_decode($data, true);
        if (empty($dataArr) || empty($dataArr[&#39;address&#39;]) || empty($dataArr[&#39;subject&#39;]) || empty($dataArr[&#39;body&#39;])) {
            $return[&#39;code&#39;] = -1;
            $return[&#39;msg&#39;] = &#39;參數(shù)不能為空&#39;;
        } else { // 參數(shù)校驗成功
            $server->task($data); // 投遞一個任務(wù)
            $return[&#39;code&#39;] = 0;
            $return[&#39;msg&#39;] = &#39;投遞任務(wù)成功&#39;;
        }
        $server->send($fd, json_encode($return));
    }

    public function onTask($server, $taskId, $workerId, $data)
    {
        $data = json_decode($data, true);
        $this->handle->send($data[&#39;address&#39;], $data[&#39;subject&#39;], $data[&#39;body&#39;]); // 發(fā)送郵件
    }

    public function onFinish($server, $task_id, $data)
    {

    }

    public function onClose($server, $fd, $reactorId)
    {

    }
}

發(fā)件人信息配置:

<?php

// 郵件發(fā)送人信息配置

return [
    &#39;host&#39; => &#39;smtp.qq.com&#39;,
    &#39;port&#39; => &#39;465&#39;,
    &#39;fromName&#39; => &#39;Mr.litt&#39;,
    &#39;username&#39; => &#39;137057181@qq.com&#39;,
    &#39;password&#39; => &#39;&#39;,
];

PHPMailer郵件服務(wù)類:

<?php

require &#39;vendor/phpmailer/phpmailer/src/Exception.php&#39;;
require &#39;vendor/phpmailer/phpmailer/src/PHPMailer.php&#39;;
require &#39;vendor/phpmailer/phpmailer/src/SMTP.php&#39;;

use PHPMailer\PHPMailer\PHPMailer;

class Mail
{
    private $host;
    private $port;
    private $fromName;
    private $username;
    private $password;

    public function __construct($config)
    {
        !empty($config[&#39;host&#39;]) && $this->host = $config[&#39;host&#39;];
        !empty($config[&#39;port&#39;]) && $this->port = $config[&#39;port&#39;];
        !empty($config[&#39;fromName&#39;]) && $this->fromName = $config[&#39;fromName&#39;];
        !empty($config[&#39;username&#39;]) && $this->username = $config[&#39;username&#39;];
        !empty($config[&#39;password&#39;]) && $this->password = $config[&#39;password&#39;];
        if (empty($this->host) || empty($this->port) || empty($this->fromName) ||
            empty($this->username) || empty($this->password)) {
            throw new Exception(&#39;發(fā)件人信息錯誤&#39;);
        }
    }

    public function send($address, $subject, $body)
    {
        if (empty($address) || empty($subject) || empty($body)) {
            throw new Exception(&#39;收件人信息錯誤&#39;);
        }
        // 實例化PHPMailer核心類
        $mail = new PHPMailer();
        // 是否啟用smtp的debug進行調(diào)試 開發(fā)環(huán)境建議開啟 生產(chǎn)環(huán)境注釋掉即可 默認(rèn)關(guān)閉debug調(diào)試模式
        $mail->SMTPDebug = 0;
        // 使用smtp鑒權(quán)方式發(fā)送郵件
        $mail->isSMTP();
        // smtp需要鑒權(quán) 這個必須是true
        $mail->SMTPAuth = true;
        // 鏈接郵箱的服務(wù)器地址
        $mail->Host = $this->host;
        // 設(shè)置使用ssl加密方式登錄鑒權(quán)
        $mail->SMTPSecure = &#39;ssl&#39;;
        // 設(shè)置ssl連接smtp服務(wù)器的遠(yuǎn)程服務(wù)器端口號
        $mail->Port = $this->port;
        // 設(shè)置發(fā)送的郵件的編碼
        $mail->CharSet = &#39;UTF-8&#39;;
        // 設(shè)置發(fā)件人昵稱 顯示在收件人郵件的發(fā)件人郵箱地址前的發(fā)件人姓名
        $mail->FromName = $this->fromName;
        // smtp登錄的賬號 QQ郵箱即可
        $mail->Username = $this->username;
        // smtp登錄的密碼 使用生成的授權(quán)碼
        $mail->Password = $this->password;
        // 設(shè)置發(fā)件人郵箱地址 同登錄賬號
        $mail->From = $this->username;
        // 郵件正文是否為html編碼 注意此處是一個方法
        $mail->isHTML(true);
        // 設(shè)置收件人郵箱地址
        $mail->addAddress($address);
        // 添加多個收件人 則多次調(diào)用方法即可
        //$mail->addAddress(&#39;87654321@163.com&#39;);
        // 添加該郵件的主題
        $mail->Subject = $subject;
        // 添加郵件正文
        $mail->Body = $body;
        // 為該郵件添加附件
        //$mail->addAttachment(&#39;./example.pdf&#39;);
        // 發(fā)送郵件 返回狀態(tài)
        $status = $mail->send();
        return $status;
    }
}

注意事項:

  1. 修改發(fā)件人信息后,只需重啟task_worker就生效,命令 kill -USER1 主進程PID。
  2. TCP客戶端可使用swoole_client類來模擬。
  3. 短信、推送等異步任務(wù)同樣適用于此場景。

基于WebSocket多房間聊天功能

使用Swoole提供WebSocket服務(wù),使用Redis保存房間人員信息。

PHP主代碼:

<?php

$object = new ChatServer();

$setting = [
    &#39;log_file&#39; => &#39;swoole_ws.log&#39;,
    &#39;worker_num&#39; => 4, // 4個工作進程
];
$ws = new swoole_websocket_server("127.0.0.1", 9502);
$ws->set($setting);

$ws->on(&#39;WorkerStart&#39;, array($object, &#39;onWorkerStart&#39;));
$ws->on(&#39;open&#39;, array($object, &#39;onOpen&#39;));
$ws->on(&#39;message&#39;, array($object, &#39;onMessage&#39;));
$ws->on(&#39;close&#39;, array($object, &#39;onClose&#39;));

$ws->start();

class ChatServer
{
    /** @var  Redis */
    private $redis;

    public function __construct()
    {
        echo "啟動前清理數(shù)據(jù)\n";
        $redis = new Redis();
        $redis->connect(&#39;127.0.0.1&#39;, 6379);
        if ($redis->ping() != &#39;+PONG&#39;) {
            echo "redis連接失敗\n";exit;
        }
        $delKeys = $redis->keys(&#39;fd_*&#39;);
        foreach ($delKeys as $key) {
            $redis->del($key);
        }
        $delKeys = $redis->keys(&#39;roomId_*&#39;);
        foreach ($delKeys as $key) {
            $redis->del($key);
        }
    }

    public function onWorkerStart($ws, $workerId)
    {
        $redis = new Redis();
        $redis->connect(&#39;127.0.0.1&#39;, 6379);
        if ($redis->ping() != &#39;+PONG&#39;) {
            echo "redis連接失敗\n";
        }
        $this->redis = $redis;
    }

    public function onOpen($ws, $request)
    {
        echo "fd:{$request->fd} is open\n";
        if (empty($request->get[&#39;roomId&#39;]) || empty($request->get[&#39;nick&#39;])) {
            $status = &#39;fail&#39;;
        } else {
            //建立身份關(guān)聯(lián)
            $this->redis->hSet("fd_".$request->fd, &#39;roomId&#39;, $request->get[&#39;roomId&#39;]);
            $this->redis->hSet("fd_".$request->fd, &#39;nick&#39;, $request->get[&#39;nick&#39;]);
            $this->redis->sAdd("roomId_".$request->get[&#39;roomId&#39;], $request->fd);

            $status = &#39;success&#39;;
        }
        $sendData = [
            &#39;cmd&#39; => &#39;open&#39;,
            &#39;data&#39; => [
                &#39;status&#39; => $status
            ]
        ];
        $ws->push($request->fd, json_encode($sendData));
    }

    public function onMessage($ws, $frame)
    {
        echo "fd:[$frame->fd}, Message: {$frame->data}\n";
        if (!empty($frame->data)) {
            $fdInfo = $this->redis->hGetAll("fd_".$frame->fd);
            if (!empty($fdInfo[&#39;nick&#39;]) && !empty($fdInfo[&#39;roomId&#39;])) {
                $sendData = [
                    &#39;cmd&#39; => &#39;ReceiveMessage&#39;,
                    &#39;data&#39; => [
                        &#39;nick&#39; => $fdInfo[&#39;nick&#39;],
                        &#39;msg&#39; => $frame->data,
                    ]
                ];
                $fdArr = $this->redis->sMembers("roomId_".$fdInfo[&#39;roomId&#39;]);
                foreach ($fdArr as $fd) {
                    $ws->push($fd, json_encode($sendData));
                }
            }
        }
    }

    public function onClose($ws, $fd, $reactorId)
    {
        echo "fd:{$fd} is closed\n";
        //刪除fd身份數(shù)據(jù)并在房間內(nèi)移動該fd
        $fdInfo = $this->redis->hGetAll("fd_".$fd);
        if (!empty($fdInfo[&#39;roomId&#39;])) {
            $this->redis->sRem("roomId_".$fdInfo[&#39;roomId&#39;], $fd);
        }
        $this->redis->del("fd_".$fd);
    }
}

注意事項:

1.Worker進程之間不能共享變量,這里使用Redis來共享數(shù)據(jù)。

2.Worker進程不能共用同一個Redis客戶端,需要放到onWorkerStart中實例化。

3.客戶端可使用JS內(nèi)置等WebSokcet客戶端,異步的PHP程序可使用Swoole\Http\Client,同步可以使用swoole/framework提供的同步WebSocket客戶端。

基于HTTP的簡易框架

使用Swoole提供HTTP服務(wù),模擬官方Swoole框架實現(xiàn)一個簡易框架。

PHP主代碼:

<?php

$object = new AppServer();

$setting = [
    &#39;log_file&#39; => &#39;swoole_http.log&#39;,
    &#39;worker_num&#39; => 4, // 4個工作進程
];
$server = new swoole_http_server("127.0.0.1", 9503);
$server->set($setting);

$server->on(&#39;request&#39;, array($object, &#39;onRequest&#39;));
$server->on(&#39;close&#39;, array($object, &#39;onClose&#39;));

$server->start();

/**
 * Class AppServer
 * @property \swoole_http_request $request
 * @property \swoole_http_response $response
 * @property \PDO $db
 * @property \lib\Session $session
 */
class AppServer
{
    private $module = [];

    /** @var AppServer */
    private static $instance;

    public static function getInstance()
    {
        return self::$instance;
    }

    public function __construct()
    {
        $baseControllerFile = __DIR__ .&#39;/controller/Base.php&#39;;
        require_once "$baseControllerFile";
    }

    /**
     * @param swoole_http_request $request
     * @param swoole_http_response $response
     */
    public function onRequest($request, $response)
    {
        $this->module[&#39;request&#39;] = $request;
        $this->module[&#39;response&#39;] = $response;
        self::$instance = $this;

        list($controllerName, $methodName) = $this->route($request);
        empty($controllerName) && $controllerName = &#39;index&#39;;
        empty($methodName) && $methodName = &#39;index&#39;;

        try {
            $controllerClass = "\\controller\\" . ucfirst($controllerName);
            $controllerFile = __DIR__ . "/controller/" . ucfirst($controllerName) . ".php";
            if (!class_exists($controllerClass, false)) {
                if (!is_file($controllerFile)) {
                    throw new Exception(&#39;控制器不存在&#39;);
                }
                require_once "$controllerFile";
            }

            $controller = new $controllerClass($this);
            if (!method_exists($controller, $methodName)) {
                throw new Exception(&#39;控制器方法不存在&#39;);
            }

            ob_start();
            $return = $controller->$methodName();
            $return .= ob_get_contents();
            ob_end_clean();
            $this->session->end();
            $response->end($return);
        } catch (Exception $e) {
            $response->status(500);
            $response->end($e->getMessage());
        }
    }

    private function route($request)
    {
        $pathInfo = explode(&#39;/&#39;, $request->server[&#39;path_info&#39;]);
        return [$pathInfo[1], $pathInfo[2]];
    }

    public function onClose($server, $fd, $reactorId)
    {

    }

    public function __get($name)
    {
        if (!in_array($name, array(&#39;request&#39;, &#39;response&#39;, &#39;db&#39;, &#39;session&#39;))) {
            return null;
        }
        if (empty($this->module[$name])) {
            $moduleClass = "\\lib\\" . ucfirst($name);
            $moduleFile = __DIR__ . &#39;/lib/&#39; . ucfirst($name) . ".php";
            if (is_file($moduleFile)) {
                require_once "$moduleFile";
                $object = new $moduleClass;
                $this->module[$name] = $object;
            }
        }
        return $this->module[$name];
    }
}

使用header和setCooike示例:

<?php

namespace controller;

class Http extends Base
{
    public function header()
    {
        //發(fā)送Http狀態(tài)碼,如500, 404等等
        $this->response->status(302);
        //使用此函數(shù)代替PHP的header函數(shù)
        $this->response->header(&#39;Location&#39;, &#39;http://www.baidu.com/&#39;);
    }

    public function cookie()
    {
        $this->response->cookie(&#39;http_cookie&#39;,&#39;http_cookie_value&#39;);
    }
}

Session實現(xiàn):

<?php

namespace lib;

class Session
{
    private $sessionId;
    private $cookieKey;
    private $storeDir;
    private $file;
    private $isStart;

    public function __construct()
    {
        $this->cookieKey = &#39;PHPSESSID&#39;;
        $this->storeDir = &#39;tmp/&#39;;
        $this->isStart = false;
    }

    public function start()
    {
        $this->isStart = true;
        $appServer = \AppServer::getInstance();
        $request = $appServer->request;
        $response = $appServer->response;
        $sessionId = $request->cookie[$this->cookieKey];
        if (empty($sessionId)){
            $sessionId = uniqid();
            $response->cookie($this->cookieKey, $sessionId);
        }
        $this->sessionId = $sessionId;
        $storeFile = $this->storeDir . $sessionId;
        if (!is_file($storeFile)) {
            touch($storeFile);
        }
        $session = $this->get($storeFile);
        $_SESSION = $session;
    }

    public function end()
    {
        $this->save();
    }

    public function commit()
    {
        $this->save();
    }

    private function save()
    {
        if ($this->isStart) {
            $data = json_encode($_SESSION);
            ftruncate($this->file, 0);

            if ($data) {
                rewind($this->file);
                fwrite($this->file, $data);
            }
            flock($this->file, LOCK_UN);
            fclose($this->file);
        }
    }

    private function get($fileName)
    {
        $this->file = fopen($fileName, &#39;c+b&#39;);
        if(flock($this->file, LOCK_EX | LOCK_NB)) {
            $data = [];
            clearstatcache();
            if (filesize($fileName) > 0) {
                $data = fread($this->file, filesize($fileName));
                $data = json_decode($data, true);
            }
            return $data;
        }
    }
}

注意事項:

  1. 使用Redis/MySQL等客戶端理應(yīng)使用線程池,參照官方Swoole框架。
  2. Swoole是在執(zhí)行PHP文件這一階段進行接管,因此header,setCooike,seesion_start不可用,header和setCooike可用$response變量實現(xiàn),Session可自行實現(xiàn)。
  3. 推薦查看官方框架:Swoole框架。

上述demo可以戳這里:demo

總結(jié)

Swoole的應(yīng)用遠(yuǎn)不如此,Swoole就像打開了PHP世界的新大門,我覺得每一位PHPer都應(yīng)該學(xué)習(xí)和掌握Swoole的用法,能學(xué)到很多使用LAMP/LNMP模式時未涉及到的知識點。

? ??? Swoole? ??? ?? ??? ?????.? ?? ?????. ??? ??? PHP ??? ????? ?? ?? ??? ?????!

? ????? ??
? ?? ??? ????? ???? ??? ??????, ???? ?????? ????. ? ???? ?? ???? ?? ??? ?? ????. ???? ??? ???? ???? ??? ?? admin@php.cn?? ?????.

? AI ??

Undresser.AI Undress

Undresser.AI Undress

???? ?? ??? ??? ?? AI ?? ?

AI Clothes Remover

AI Clothes Remover

???? ?? ???? ??? AI ?????.

Video Face Swap

Video Face Swap

??? ??? AI ?? ?? ??? ???? ?? ???? ??? ?? ????!

???

??? ??

???++7.3.1

???++7.3.1

???? ?? ?? ?? ???

SublimeText3 ??? ??

SublimeText3 ??? ??

??? ??, ???? ?? ????.

???? 13.0.1 ???

???? 13.0.1 ???

??? PHP ?? ?? ??

???? CS6

???? CS6

??? ? ?? ??

SublimeText3 Mac ??

SublimeText3 Mac ??

? ??? ?? ?? ?????(SublimeText3)

???

??? ??

??? ????
1601
29
PHP ????
1502
276
???
Laravel?? Swoole ???? ???? ?? Laravel?? Swoole ???? ???? ?? Apr 09, 2024 pm 06:48 PM

Laravel?? Swoole ???? ???? ?? ?? ??? ??? ??? ? ????. ??? ??? ????. ?? ??: ?? ??? ??? ??? ? ????. ???: Linux epoll ??? ????? ???? ??? ????? ?????. ?? ??? ??: ? ?? ?? ???? ?????. ??? ??: Laravel ?????? ???? ???? ??? ?????.

Swoole? ???? ??? HTTP ??? ??? ??? ???? ?? Swoole? ???? ??? HTTP ??? ??? ??? ???? ?? Nov 07, 2023 am 08:18 AM

Swoole? ???? ??? HTTP ??? ??? ??? ???? ?? Swoole? PHP ??? ???? ?? ???, ???? ?? ???? ?? ????????. ??? ???? ??? ???? HTTP ??, WebSocket ?? ?? ???? ? ??? ? ????. ? ????? Swoole? ???? ??? HTTP ??? ??? ??? ???? ??? ???? ???? ?? ??? ?????. ?? ?? ?? ??? Swoole ?? ????? ???? ???.

??? ??? ? ?? ?? ? ???? ??? ??? ? ?? ?? ? ???? Apr 09, 2024 pm 07:00 PM

Swoole? Workerman? ?? ??? PHP ?? ????????. ??? ??, ??? ?? ? ????? ? ??? Swoole? ?? ?? ?? ??? ?? ???? ???? ?? ????? ?????. Workerman? ?? ???? ?? ??? ??? ???? ????? ? ??? ???? API? ?? ???? ? ??? ??? ???? ?????.

Swoole ?? Java ? ?? ?? ? ?? ??? ??? ????? Swoole ?? Java ? ?? ?? ? ?? ??? ??? ????? Apr 09, 2024 pm 07:03 PM

?? ??: ???: Swoole? ??? ???? ??? ???? ? ????. ?? ??: Swoole? ??? ???? ??? ????? ?? ?? ??? ? ????. ??? ??: Swoole? ???? ? ?? ???? ?????. ?? ???: Swoole? ???? ?? ?? ????? API? ?????.

Swoole ??????? ???? ?? ???? ?? Swoole ??????? ???? ?? ???? ?? Apr 09, 2024 pm 06:15 PM

Swoole ???? ?? ????? ?? ??? ?????. ??? ??? ???? PID? ?????. ???? ????? "kill -15 PID"? ??????. ???? ???? ? ??? ?? ??? ??? ???? ???? ?? ?????.

Swoole? ?? ??: ?? ?? ??? ?? ???? ???? ?? Swoole? ?? ??: ?? ?? ??? ?? ???? ???? ?? Nov 07, 2023 pm 02:55 PM

Swoole? ?? ??: ?? ?? ??? ?? ???? ???? ?? ?? ???? ???? ??? ??? ?? ??? ???? ?? ??? ?? ?????. ???? ?? ??? ?? ??? ?? ?? ????? ???? ?? ??? ???? ???? ? ???? ?? ? ??? ?? ???? ?? ??? ????. ???? ???? PHP? ????? ??? ???? ?? ?? ??? ?? ?? ???? ??? ?? ??? ? ????. ??? Swoole ??? ?????? ???? ???? ???? ??? ?? ?? ??? ??? ? ????. ? ??? ???

swoole_process? ???? ???? ??? ??? ? ???? swoole_process? ???? ???? ??? ??? ? ???? Apr 09, 2024 pm 06:21 PM

Swoole ????? ?? ???? ????? ???? ????? ??? ? ????.

Swoole? ???? WebSocket ??? ???? ?? Swoole? ???? WebSocket ??? ???? ?? Nov 07, 2023 pm 12:56 PM

Swoole? ??? IO, ?? ????, ?? ???, ??? ? ?? ??? ???? ??? PHP ??? ???? ????????. ?? Swoole?? ???? WebSocket ?? ??? ??? ??? ??? ???? ? ??? ? ??? ??? ??????? ???? ? ???? ?????. ? ????? Swoole? ???? WebSocket ??? ???? ??? ???? ?? ?? ??? ?????. 1. ?? ?? Swoole? ???? WebSocket ??? ???? ?? Swoole ??? ???? ??? ???? ???. ???

See all articles