成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Swoole 多協(xié)議 多端口 的應(yīng)用

wenshi11019 / 2235人閱讀

摘要:概述這是關(guān)于學(xué)習(xí)的第五篇文章多協(xié)議多端口的應(yīng)用。網(wǎng)絡(luò)通信協(xié)議設(shè)計(jì)多端口監(jiān)聽的使用希望通過我提供的,能夠?qū)ξ臋n有更加深刻的理解。支持了種類型的自定義網(wǎng)絡(luò)通信協(xié)議結(jié)束符協(xié)議固定包頭包體協(xié)議。

概述

這是關(guān)于 Swoole 學(xué)習(xí)的第五篇文章:Swoole 多協(xié)議 多端口 的應(yīng)用。

第四篇:Swoole HTTP 的應(yīng)用

第三篇:Swoole WebSocket 的應(yīng)用

第二篇:Swoole Task 的應(yīng)用

第一篇:Swoole Timer 的應(yīng)用

主要參考官方的這兩篇文章,進(jìn)行實(shí)現(xiàn)的 Demo。

網(wǎng)絡(luò)通信協(xié)議設(shè)計(jì):https://wiki.swoole.com/wiki/...

多端口監(jiān)聽的使用:https://wiki.swoole.com/wiki/...

希望通過我提供的 Demo,能夠?qū)ξ臋n有更加深刻的理解。

網(wǎng)絡(luò)通信協(xié)議設(shè)計(jì)

為什么需要通信協(xié)議?

官方:TCP協(xié)議在底層機(jī)制上解決了UDP協(xié)議的順序和丟包重傳問題。但相比UDP又帶來了新的問題,TCP協(xié)議是流式的,數(shù)據(jù)包沒有邊界。應(yīng)用程序使用TCP通信就會(huì)面臨這些難題。因?yàn)門CP通信是流式的,在接收1個(gè)大數(shù)據(jù)包時(shí),可能會(huì)被拆分成多個(gè)數(shù)據(jù)包發(fā)送。多次Send底層也可能會(huì)合并成一次進(jìn)行發(fā)送。這里就需要2個(gè)操作來解決:分包 和 合包,所以TCP網(wǎng)絡(luò)通信時(shí)需要設(shè)定通信協(xié)議。

Swoole 支持了2種類型的自定義網(wǎng)絡(luò)通信協(xié)議 :EOF結(jié)束符協(xié)議、固定包頭+包體協(xié)議。

EOF結(jié)束符協(xié)議

先看下,未設(shè)置協(xié)議的效果:

發(fā)送的每條數(shù)據(jù)長(zhǎng)度都是 23,但在 onReceive 接收數(shù)據(jù)的時(shí)候每次接收的長(zhǎng)度不一樣,并沒有按照想象的方式進(jìn)行分包。

再看下,設(shè)置了EOF結(jié)束符協(xié)議的效果:

發(fā)送的每條數(shù)據(jù)長(zhǎng)度都是 23,在 onReceive 接收數(shù)據(jù)的時(shí)候每次接收的也是 23 ,完美。

主要設(shè)置項(xiàng)如下:

"package_max_length" => "8192",
"open_eof_split"     => true,
"package_eof"        => "
"

不做解釋,官方文檔已經(jīng)寫的很清楚。

示例代碼如下:

server.php

serv = new swoole_server("0.0.0.0", 9501);
        $this->serv->set([
            "worker_num"      => 2, //開啟2個(gè)worker進(jìn)程
            "max_request"     => 4, //每個(gè)worker進(jìn)程 max_request設(shè)置為4次
            "dispatch_mode"   => 2, //數(shù)據(jù)包分發(fā)策略 - 固定模式

            //EOF結(jié)束符協(xié)議
            "package_max_length" => "8192",
            "open_eof_split"     => true,
            "package_eof"        => "
"
        ]);

        $this->serv->on("Start", [$this, "onStart"]);
        $this->serv->on("Connect", [$this, "onConnect"]);
        $this->serv->on("Receive", [$this, "onReceive"]);
        $this->serv->on("Close", [$this, "onClose"]);

        $this->serv->start();
    }

    public function onStart($serv) {
        echo "#### onStart ####".PHP_EOL;
        echo "SWOOLE ".SWOOLE_VERSION . " 服務(wù)已啟動(dòng)".PHP_EOL;
        echo "swoole_cpu_num:".swoole_cpu_num().PHP_EOL;
        echo "master_pid: {$serv->master_pid}".PHP_EOL;
        echo "manager_pid: {$serv->manager_pid}".PHP_EOL;
        echo "########".PHP_EOL.PHP_EOL;
    }

    public function onConnect($serv, $fd) {
        echo "#### onConnect ####".PHP_EOL;
        echo "客戶端:".$fd." 已連接".PHP_EOL;
        echo "########".PHP_EOL.PHP_EOL;
    }

    public function onReceive($serv, $fd, $from_id, $data) {
        echo "#### onReceive ####".PHP_EOL;
        var_dump($data);
    }

    public function onClose($serv, $fd) {
        echo "Client Close.".PHP_EOL;
    }
}

$server = new Server();

client.php

client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);

        $this->client->on("Connect", [$this, "onConnect"]);
        $this->client->on("Close", [$this, "onClose"]);
        $this->client->on("Error", [$this, "onError"]);
    }

    public function connect() {
        if(!$fp = $this->client->connect("127.0.0.1", 9501)) {
            echo "Error: {$fp->errMsg}[{$fp->errCode}]".PHP_EOL;
            return;
        }
    }

    public function onConnect() {

        fwrite(STDOUT, "發(fā)送測(cè)試數(shù)據(jù)(Y or N):");
        swoole_event_add(STDIN, function() {
            $msg = trim(fgets(STDIN));
            if ($msg == "y") {
                $this->send();
            }
            fwrite(STDOUT, "發(fā)送測(cè)試數(shù)據(jù)(Y or N):");
        });
    }

    public function send() {
        $msg_info =  "客戶端發(fā)信息...
";

        $i = 0;
        while ($i < 50) {
            var_dump($msg_info);
            $this->client->send($msg_info);
            $i++;
        }
    }

    public function onClose() {
        echo "Client close connection".PHP_EOL;
    }

    public function onError() {

    }
}

$client = new Client();
$client->connect();
固定包頭+包體協(xié)議

先看下,未設(shè)置協(xié)議的效果:

很明顯,在 onReceive 接收到的數(shù)據(jù),是少的。

再看下,設(shè)置協(xié)議的效果:

主要設(shè)置項(xiàng)如下:

"open_length_check"     => true,
"package_max_length"    => "8192",
"package_length_type"   => "N",
"package_length_offset" => "0",
"package_body_offset"   => "4",

不做解釋,官方文檔已經(jīng)寫的很清楚。

示例代碼如下:

server.php

serv = new swoole_server("0.0.0.0", 9501);
        $this->serv->set([
            "worker_num"      => 2, //開啟2個(gè)worker進(jìn)程
            "max_request"     => 4, //每個(gè)worker進(jìn)程 max_request設(shè)置為4次
            "dispatch_mode"   => 2, //數(shù)據(jù)包分發(fā)策略 - 固定模式

            //固定包頭+包體協(xié)議
            "open_length_check"     => true,
            "package_max_length"    => "8192",
            "package_length_type"   => "N",
            "package_length_offset" => "0",
            "package_body_offset"   => "4",
        ]);

        $this->serv->on("Start", [$this, "onStart"]);
        $this->serv->on("Connect", [$this, "onConnect"]);
        $this->serv->on("Receive", [$this, "onReceive"]);
        $this->serv->on("Close", [$this, "onClose"]);

        $this->serv->start();
    }

    public function onStart($serv) {
        echo "#### onStart ####".PHP_EOL;
        echo "swoole_cpu_num:".swoole_cpu_num().PHP_EOL;
        echo "SWOOLE ".SWOOLE_VERSION . " 服務(wù)已啟動(dòng)".PHP_EOL;
        echo "master_pid: {$serv->master_pid}".PHP_EOL;
        echo "manager_pid: {$serv->manager_pid}".PHP_EOL;
        echo "########".PHP_EOL.PHP_EOL;
    }

    public function onConnect($serv, $fd) {
        echo "#### onConnect ####".PHP_EOL;
        echo "客戶端:".$fd." 已連接".PHP_EOL;
        echo "########".PHP_EOL.PHP_EOL;
    }

    public function onReceive($serv, $fd, $from_id, $data) {
        echo "#### onReceive ####".PHP_EOL;
        $length = unpack("N", $data)[1];
        echo "Length:".$length.PHP_EOL;
        $msg = substr($data, -$length);
        echo "Msg:".$msg.PHP_EOL;
    }

    public function onClose($serv, $fd) {
        echo "Client Close.".PHP_EOL;
    }
}

$server = new Server();

client.php

client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);

        $this->client->on("Connect", [$this, "onConnect"]);
        $this->client->on("Close", [$this, "onClose"]);
        $this->client->on("Error", [$this, "onError"]);
    }

    public function connect() {
        if(!$fp = $this->client->connect("127.0.0.1", 9501, 1)) {
            echo "Error: {$fp->errMsg}[{$fp->errCode}]".PHP_EOL;
            return;
        }
    }

    public function onConnect() {

        fwrite(STDOUT, "發(fā)送測(cè)試數(shù)據(jù)(Y or N):");
        swoole_event_add(STDIN, function() {
            $msg = trim(fgets(STDIN));
            if ($msg == "y") {
                $this->send();
            }
            fwrite(STDOUT, "發(fā)送測(cè)試數(shù)據(jù)(Y or N):");
        });
    }

    public function send() {
        $msg = "客戶端發(fā)的信息...";
        $msg_info = pack("N", strlen($msg)).$msg;

        $i = 0;
        while ($i < 50) {
            var_dump($msg_info);
            $this->client->send($msg_info);
            $i++;
        }
    }

    public function onClose() {
        echo "Client close connection".PHP_EOL;
    }

    public function onError() {

    }
}

$client = new Client();
$client->connect();
多端口監(jiān)聽的使用

上圖,是示例代碼中的端口監(jiān)聽:

9501 onMessage 處理 WebSocket。

9501 onRequest 處理 HTTP。

9502 onReceive 處理 TCP。

9503 onPacket 處理 UDP。

不多說,看下效果圖:

示例代碼如下:

server.php

serv = new swoole_websocket_server("0.0.0.0", 9501);
        $this->serv->set([
            "worker_num"      => 2, //開啟2個(gè)worker進(jìn)程
            "max_request"     => 4, //每個(gè)worker進(jìn)程 max_request設(shè)置為4次
            "task_worker_num" => 4, //開啟4個(gè)task進(jìn)程
            "dispatch_mode"   => 4, //數(shù)據(jù)包分發(fā)策略 - IP分配
            "daemonize"       => false, //守護(hù)進(jìn)程(true/false)
        ]);

        $this->serv->on("Start", [$this, "onStart"]);
        $this->serv->on("Open", [$this, "onOpen"]);
        $this->serv->on("Message", [$this, "onMessage"]);
        $this->serv->on("Request", [$this, "onRequest"]);
        $this->serv->on("Close", [$this, "onClose"]);
        $this->serv->on("Task", [$this, "onTask"]);
        $this->serv->on("Finish", [$this, "onFinish"]);

        //監(jiān)聽 9502 端口
        $tcp = $this->serv->listen("0.0.0.0", 9502, SWOOLE_SOCK_TCP);
        $tcp->set([
            "worker_num"      => 2, //開啟2個(gè)worker進(jìn)程
            "max_request"     => 4, //每個(gè)worker進(jìn)程 max_request設(shè)置為4次
            "dispatch_mode"   => 2, //數(shù)據(jù)包分發(fā)策略 - 固定模式

            //固定包頭+包體協(xié)議
            "open_length_check"     => true,
            "package_max_length"    => "8192",
            "package_length_type"   => "N",
            "package_length_offset" => "0",
            "package_body_offset"   => "4",
        ]);
        $tcp->on("Receive", [$this, "onReceive"]);

        //監(jiān)聽 9503 端口
        $udp = $this->serv->listen("0.0.0.0", 9503, SWOOLE_SOCK_UDP);
        $udp->set([
            "worker_num"      => 2, //開啟2個(gè)worker進(jìn)程
            "max_request"     => 4, //每個(gè)worker進(jìn)程 max_request設(shè)置為4次
            "dispatch_mode"   => 2, //數(shù)據(jù)包分發(fā)策略 - 固定模式
        ]);
        $udp->on("Packet", [$this, "onPacket"]);

        $this->serv->start();
    }

    public function onStart($serv) {
        echo "#### onStart ####".PHP_EOL;
        echo "SWOOLE ".SWOOLE_VERSION . " 服務(wù)已啟動(dòng)".PHP_EOL;
        echo "master_pid: {$serv->master_pid}".PHP_EOL;
        echo "manager_pid: {$serv->manager_pid}".PHP_EOL;
        echo "########".PHP_EOL.PHP_EOL;
    }

    public function onOpen($serv, $request) {
        echo "#### onOpen ####".PHP_EOL;
        echo "server: handshake success with fd{$request->fd}".PHP_EOL;
        $serv->task([
            "type" => "login"
        ]);
        echo "########".PHP_EOL.PHP_EOL;
    }

    public function onTask($serv, $task_id, $from_id, $data) {
        echo "#### onTask ####".PHP_EOL;
        echo "#{$serv->worker_id} onTask: [PID={$serv->worker_pid}]: task_id={$task_id}".PHP_EOL;
        $msg = "";
        switch ($data["type"]) {
            case "login":
                $msg = "我來了...";
                break;
            case "speak":
                $msg = $data["msg"];
                break;
        }
        foreach ($serv->connections as $fd) {
            $connectionInfo = $serv->connection_info($fd);
            if (isset($connectionInfo["websocket_status"]) && $connectionInfo["websocket_status"] == 3) {
                $serv->push($fd, $msg); //長(zhǎng)度最大不得超過2M
            }
        }
        $serv->finish($data);
        echo "########".PHP_EOL.PHP_EOL;
    }

    public function onFinish($serv,$task_id, $data) {
        echo "#### onFinish ####".PHP_EOL;
        echo "Task {$task_id} 已完成".PHP_EOL;
        echo "########".PHP_EOL.PHP_EOL;
    }

    public function onClose($serv, $fd) {
        echo "#### onClose ####".PHP_EOL;
        echo "client {$fd} closed".PHP_EOL;
        echo "########".PHP_EOL.PHP_EOL;
    }

    public function onMessage($serv, $frame) {
        echo "#### onMessage ####".PHP_EOL;
        echo "receive from fd{$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}".PHP_EOL;
        $serv->task(["type" => "speak", "msg" => $frame->data]);
        echo "########".PHP_EOL.PHP_EOL;
    }

    public function onRequest($request, $response) {
        echo "#### onRequest ####".PHP_EOL;
        $response->header("Content-Type", "text/html; charset=utf-8");
        $server = $request->server;
        $path_info    = $server["path_info"];
        $request_uri  = $server["request_uri"];

        echo "PATH_INFO:".$path_info.PHP_EOL;

        if ($path_info == "/favicon.ico" || $request_uri == "/favicon.ico") {
            return $response->end();
        }

        $html = "

你好 Swoole.

"; $response->end($html); } public function onReceive($serv, $fd, $from_id, $data) { echo "#### onReceive ####".PHP_EOL; $length = unpack("N", $data)[1]; echo "Length:".$length.PHP_EOL; $msg = substr($data, -$length); echo "Msg:".$msg.PHP_EOL; } public function onPacket($serv, $data, $clientInfo) { echo "#### onPacket ####".PHP_EOL; $serv->sendto($clientInfo["address"], $clientInfo["port"], "Server ".$data); var_dump($clientInfo); } } $server = new Server();

4 個(gè)客戶端連接的代碼分別是:

1、9501 onMessage 處理 WebSocket??梢詤⒖荚瓉砦恼?Swoole WebSocket 的應(yīng)用 中的代碼即可。

2、9501 onRequest 處理 HTTP??梢詤⒖荚瓉砦恼?Swoole HTTP 的應(yīng)用 中的代碼即可。

3、9502 onReceive 處理 TCP。可以參考原來文章 Swoole Task 的應(yīng)用 中的代碼即可。

4、9503 onPacket 處理 UDP。

示例代碼:

netcat -u 10.211.55.4 9503
小結(jié)

一、多端口的應(yīng)用場(chǎng)景是什么?

比如,開發(fā)一個(gè)直播網(wǎng)站,直播用一個(gè)端口,IM聊天用一個(gè)端口。

比如,開發(fā)一個(gè)RPC服務(wù),數(shù)據(jù)通訊用一個(gè)端口,統(tǒng)計(jì)界面用一個(gè)端口。

推薦閱讀

系統(tǒng)的講解 - SSO 單點(diǎn)登錄

系統(tǒng)的講解 - PHP WEB 安全防御

系統(tǒng)的講解 - PHP 緩存技術(shù)

系統(tǒng)的講解 - PHP 接口簽名驗(yàn)證

系統(tǒng)的講解 - PHP 浮點(diǎn)數(shù)高精度運(yùn)算

本文歡迎轉(zhuǎn)發(fā),轉(zhuǎn)發(fā)請(qǐng)注明作者和出處,謝謝!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/31480.html

相關(guān)文章

  • swoolefy-基于swoole擴(kuò)展實(shí)現(xiàn)高性能常駐內(nèi)存型API和Web應(yīng)用服務(wù)框架

    摘要:是一個(gè)基于擴(kuò)展實(shí)現(xiàn)的輕量級(jí)高性能的常駐內(nèi)存型的和應(yīng)用服務(wù)框架高度封裝了,,服務(wù)器,以及基于實(shí)現(xiàn)可擴(kuò)展的服務(wù),同時(shí)支持包方式安裝部署項(xiàng)目?;趯?shí)用,抽象事件處理類,實(shí)現(xiàn)與底層的回調(diào)的解耦,支持同步異步調(diào)用,內(nèi)置等常用組件等。 swoolefy swoolefy是一個(gè)基于swoole擴(kuò)展實(shí)現(xiàn)的輕量級(jí)高性能的常駐內(nèi)存型的API和Web應(yīng)用服務(wù)框架,高度封裝了http,websocket,ud...

    lewinlee 評(píng)論0 收藏0
  • Swoole源碼研究】淺析swoole中server實(shí)現(xiàn)

    摘要:的部分是基于以及協(xié)議的。例如父進(jìn)程向中寫入子進(jìn)程從中讀取子進(jìn)程向中寫入父進(jìn)程從中讀取。默認(rèn)使用對(duì)進(jìn)程進(jìn)行分配交給對(duì)應(yīng)的線程進(jìn)行監(jiān)聽線程收到某個(gè)進(jìn)程的數(shù)據(jù)后會(huì)進(jìn)行處理值得注意的是這個(gè)線程可能并不是發(fā)送請(qǐng)求的那個(gè)線程。 作者:施洪寶 一. 基礎(chǔ)知識(shí) 1.1 swoole swoole是面向生產(chǎn)環(huán)境的php異步網(wǎng)絡(luò)通信引擎, php開發(fā)人員可以利用swoole開發(fā)出高性能的server服務(wù)。...

    rainyang 評(píng)論0 收藏0
  • Swoole MySQL 連接池實(shí)現(xiàn)

    摘要:概述這是關(guān)于入門學(xué)習(xí)的第八篇文章連接池的實(shí)現(xiàn)。開始今天的文章,這篇文章實(shí)現(xiàn)了連接池,代碼是在的實(shí)現(xiàn)文章的基礎(chǔ)上進(jìn)行開發(fā)的。 概述 這是關(guān)于 Swoole 入門學(xué)習(xí)的第八篇文章:Swoole MySQL 連接池的實(shí)現(xiàn)。 第七篇:Swoole RPC 的實(shí)現(xiàn) 第六篇:Swoole 整合成一個(gè)小框架 第五篇:Swoole 多協(xié)議 多端口 的應(yīng)用 第四篇:Swoole HTTP 的應(yīng)用 第三...

    13651657101 評(píng)論0 收藏0
  • Swoole RPC 實(shí)現(xiàn)

    摘要:概述這是關(guān)于學(xué)習(xí)的第七篇文章的實(shí)現(xiàn)。還有一些大佬加了微信,可能是出于對(duì)晚輩的提攜吧,偷偷告訴你,從大佬的朋友圈能學(xué)到很多東西。就到這了,上面的需要源碼的,加我微信。 概述 這是關(guān)于 Swoole 學(xué)習(xí)的第七篇文章:Swoole RPC 的實(shí)現(xiàn)。 第六篇:Swoole 整合成一個(gè)小框架 第五篇:Swoole 多協(xié)議 多端口 的應(yīng)用 第四篇:Swoole HTTP 的應(yīng)用 第三篇:Swo...

    FWHeart 評(píng)論0 收藏0
  • 壓測(cè) swoole_websocket_server 性能

    摘要:概述這是關(guān)于入門學(xué)習(xí)的第十篇文章壓測(cè)性能。測(cè)試機(jī)上安裝的虛擬機(jī)系統(tǒng)內(nèi)存數(shù)量核數(shù)數(shù)量大小代碼壓測(cè)腳本并發(fā)量請(qǐng)求量壓測(cè)結(jié)果第次第次第次以上是壓測(cè)結(jié)果,供參考。小結(jié)通過這個(gè)壓測(cè)結(jié)果,表明的執(zhí)行效率是杠杠的當(dāng)然還有一些參數(shù)是可以調(diào)優(yōu)的,比如等。 概述 這是關(guān)于 Swoole 入門學(xué)習(xí)的第十篇文章:壓測(cè) swoole_websocket_server 性能。 第九篇:Swoole Redis ...

    余學(xué)文 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<