亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

實戰(zhàn) swoole【聊天室】

andycall / 2445人閱讀

摘要:是一個請求對象,包含了客戶端發(fā)來的握手請求信息事件函數(shù)中可以調(diào)用向客戶端發(fā)送數(shù)據(jù)或者調(diào)用關(guān)閉連接事件回調(diào)是可選的當服務(wù)器收到來自客戶端的數(shù)據(jù)幀時會回調(diào)此函數(shù)。

前言:了解概念之后就應(yīng)該練練手啦,不然就是巨嬰

有收獲的話請加顆小星星,沒有收獲的話可以 反對 沒有幫助 舉報三連

代碼倉庫

實戰(zhàn)swoole【聊天室】

在線體驗

準備工作

需要先看初識swoole【上】,了解基本的服務(wù)端WebSocket使用

js WebSocket客戶端簡單使用

使用
# 命令行1
php src/websocket/run.php
# 命令行2
cd public && php -S localhost:8000
# 客戶端,多開幾個查看效果
訪問http://localhost:8000/
WebSocket

官方示例

$server = new swoole_websocket_server("0.0.0.0", 9501);
$server->on("open", function (swoole_websocket_server $server, $request) {
        echo "server: handshake success with fd{$request->fd}
";
    });
$server->on("message", function (swoole_websocket_server $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 ($ser, $fd) {
        echo "client {$fd} closed
";
    });
$server->on("request", function (swoole_http_request $request, swoole_http_response $response) {
        global $server;//調(diào)用外部的server
        // $server->connections 遍歷所有websocket連接用戶的fd,給所有用戶推送
        foreach ($server->connections as $fd) {
            $server->push($fd, $request->get["message"]);
        }
    });
$server->start();

詳解:

swoole_websocket_server 繼承自 swoole_http_server

設(shè)置了onRequest回調(diào),websocket服務(wù)器也可以同時作為http服務(wù)器

未設(shè)置onRequest回調(diào),websocket服務(wù)器收到http請求后會返回http 400錯誤頁面

如果想通過接收http觸發(fā)所有websocket的推送,需要注意作用域的問題,面向過程請使用global對swoole_websocket_server進行引用,面向?qū)ο罂梢园裺woole_websocket_server設(shè)置成一個成員屬性

function onOpen(swoole_websocket_server $svr, swoole_http_request $req);

當WebSocket客戶端與服務(wù)器建立連接并完成握手后會回調(diào)此函數(shù)。

$req 是一個Http請求對象,包含了客戶端發(fā)來的握手請求信息

onOpen事件函數(shù)中可以調(diào)用push向客戶端發(fā)送數(shù)據(jù)或者調(diào)用close關(guān)閉連接

onOpen事件回調(diào)是可選的

function onMessage(swoole_websocket_server $server, swoole_websocket_frame $frame)

當服務(wù)器收到來自客戶端的數(shù)據(jù)幀時會回調(diào)此函數(shù)。

$frame 是swoole_websocket_frame對象,包含了客戶端發(fā)來的數(shù)據(jù)幀信息

onMessage回調(diào)必須被設(shè)置,未設(shè)置服務(wù)器將無法啟動

客戶端發(fā)送的ping幀不會觸發(fā)onMessage,底層會自動回復pong包

swoole_websocket_frame 屬性

$frame->fd,客戶端的socket id,使用$server->push推送數(shù)據(jù)時需要用到

$frame->data,數(shù)據(jù)內(nèi)容,可以是文本內(nèi)容也可以是二進制數(shù)據(jù),可以通過opcode的值來判斷

$frame->opcode,WebSocket的OpCode類型,可以參考WebSocket協(xié)議標準文檔

$frame->finish, 表示數(shù)據(jù)幀是否完整,一個WebSocket請求可能會分成多個數(shù)據(jù)幀進行發(fā)送(底層已經(jīng)實現(xiàn)了自動合并數(shù)據(jù)幀,現(xiàn)在不用擔心接收到的數(shù)據(jù)幀不完整)

聊天室服務(wù)端示例

目錄結(jié)構(gòu):

config

socket.php

src

websocket

Config.php

run.php

WebSocketServer.php 內(nèi)存表版本

WsRedisServer.php redis版本

WebSocketServer.php 內(nèi)存表版本

createTable();
        // 實例化配置
        $this->config = Config::getInstance();
    }

    public function run()
    {
        $this->server = new swoole_websocket_server(
            $this->config["socket"]["host"],
            $this->config["socket"]["port"]
        );

        $this->server->on("open", [$this, "open"]);
        $this->server->on("message", [$this, "message"]);
        $this->server->on("close", [$this, "close"]);

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

    public function open(swoole_websocket_server $server, swoole_http_request $request)
    {
        $user = [
            "fd" => $request->fd,
            "name" => $this->config["socket"]["name"][array_rand($this->config["socket"]["name"])] . $request->fd,
            "avatar" => $this->config["socket"]["avatar"][array_rand($this->config["socket"]["avatar"])]
        ];
        // 放入內(nèi)存表
        $this->table->set($request->fd, $user);

        $server->push($request->fd, json_encode(
                array_merge(["user" => $user], ["all" => $this->allUser()], ["type" => "openSuccess"])
            )
        );
    }

    private function allUser()
    {
        $users = [];
        foreach ($this->table as $row) {
            $users[] = $row;
        }
        return $users;
    }

    public function message(swoole_websocket_server $server, swoole_websocket_frame $frame)
    {
        $this->pushMessage($server, $frame->data, "message", $frame->fd);
    }

    /**
     * 推送消息
     *
     * @param swoole_websocket_server $server
     * @param string $message
     * @param string $type
     * @param int $fd
     */
    private function pushMessage(swoole_websocket_server $server, string $message, string $type, int $fd)
    {
        $message = htmlspecialchars($message);
        $datetime = date("Y-m-d H:i:s", time());
        $user = $this->table->get($fd);

        foreach ($this->table as $item) {
            // 自己不用發(fā)送
            if ($item["fd"] == $fd) {
                continue;
            }

            $server->push($item["fd"], json_encode([
                "type" => $type,
                "message" => $message,
                "datetime" => $datetime,
                "user" => $user
            ]));
        }
    }

    /**
     * 客戶端關(guān)閉的時候
     *
     * @param swoole_websocket_server $server
     * @param int $fd
     */
    public function close(swoole_websocket_server $server, int $fd)
    {
        $user = $this->table->get($fd);
        $this->pushMessage($server, "{$user["name"]}離開聊天室", "close", $fd);
        $this->table->del($fd);
    }

    /**
     * 創(chuàng)建內(nèi)存表
     */
    private function createTable()
    {
        $this->table = new swoole_table(1024);
        $this->table->column("fd", swoole_table::TYPE_INT);
        $this->table->column("name", swoole_table::TYPE_STRING, 255);
        $this->table->column("avatar", swoole_table::TYPE_STRING, 255);
        $this->table->create();
    }
}

WsRedisServer.php redis版本

config = Config::getInstance();
        // redis
        $this->initRedis();
        // 初始化,主要是服務(wù)端自己關(guān)閉不會清空redis
        foreach ($this->allUser() as $item) {
            $this->client->hdel("{$this->key}:{$item["fd"]}", ["fd", "name", "avatar"]);
        }
    }

    public function run()
    {
        $this->server = new swoole_websocket_server(
            $this->config["socket"]["host"],
            $this->config["socket"]["port"]
        );

        $this->server->on("open", [$this, "open"]);
        $this->server->on("message", [$this, "message"]);
        $this->server->on("close", [$this, "close"]);

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

    public function open(swoole_websocket_server $server, swoole_http_request $request)
    {
        $user = [
            "fd" => $request->fd,
            "name" => $this->config["socket"]["name"][array_rand($this->config["socket"]["name"])] . $request->fd,
            "avatar" => $this->config["socket"]["avatar"][array_rand($this->config["socket"]["avatar"])]
        ];
        // 放入redis
        $this->client->hmset("{$this->key}:{$user["fd"]}", $user);

        // 給每個人推送,包括自己
        foreach ($this->allUser() as $item) {
            $server->push($item["fd"], json_encode([
                "user" => $user,
                "all" => $this->allUser(),
                "type" => "openSuccess"
            ]));
        }
    }

    private function allUser()
    {
        $users = [];
        $keys = $this->client->keys("{$this->key}:*");
        // 所有的key
        foreach ($keys as $k => $item) {
            $users[$k]["fd"] = $this->client->hget($item, "fd");
            $users[$k]["name"] = $this->client->hget($item, "name");
            $users[$k]["avatar"] = $this->client->hget($item, "avatar");
        }
        return $users;
    }

    public function message(swoole_websocket_server $server, swoole_websocket_frame $frame)
    {
        $this->pushMessage($server, $frame->data, "message", $frame->fd);
    }

    /**
     * 推送消息
     *
     * @param swoole_websocket_server $server
     * @param string $message
     * @param string $type
     * @param int $fd
     */
    private function pushMessage(swoole_websocket_server $server, string $message, string $type, int $fd)
    {
        $message = htmlspecialchars($message);
        $datetime = date("Y-m-d H:i:s", time());
        $user["fd"] = $this->client->hget("{$this->key}:{$fd}", "fd");
        $user["name"] = $this->client->hget("{$this->key}:{$fd}", "name");
        $user["avatar"] = $this->client->hget("{$this->key}:{$fd}", "avatar");

        foreach ($this->allUser() as $item) {
            // 自己不用發(fā)送
            if ($item["fd"] == $fd) {
                continue;
            }

            $is_push = $server->push($item["fd"], json_encode([
                "type" => $type,
                "message" => $message,
                "datetime" => $datetime,
                "user" => $user
            ]));
            // 刪除失敗的推送
            if (!$is_push) {
                $this->client->hdel("{$this->key}:{$item["fd"]}", ["fd", "name", "avatar"]);
            }
        }
    }

    /**
     * 客戶端關(guān)閉的時候
     *
     * @param swoole_websocket_server $server
     * @param int $fd
     */
    public function close(swoole_websocket_server $server, int $fd)
    {
        $user["fd"] = $this->client->hget("{$this->key}:{$fd}", "fd");
        $user["name"] = $this->client->hget("{$this->key}:{$fd}", "name");
        $user["avatar"] = $this->client->hget("{$this->key}:{$fd}", "avatar");
        $this->pushMessage($server, "{$user["name"]}離開聊天室", "close", $fd);
        $this->client->hdel("{$this->key}:{$fd}", ["fd", "name", "avatar"]);
    }

    /**
     * 初始化redis
     */
    private function initRedis()
    {
        $this->client = new Client([
            "scheme" => $this->config["socket"]["redis"]["scheme"],
            "host" => $this->config["socket"]["redis"]["host"],
            "port" => $this->config["socket"]["redis"]["port"],
        ]);
    }
}

config.php

path = __DIR__ . "/../../config/";
    }

    // 單例模式
    public static function getInstance()
    {
        if (!self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function offsetSet($offset, $value)
    {
        // 閹割
    }

    public function offsetGet($offset)
    {
        if (empty($this->config)) {
            $this->config[$offset] = require $this->path . $offset . ".php";
        }
        return $this->config[$offset];
    }

    public function offsetExists($offset)
    {
        return isset($this->config[$offset]);
    }

    public function offsetUnset($offset)
    {
        // 閹割
    }

    // 禁止克隆
    final private function __clone(){}
}

config/socket.php

 "0.0.0.0",
    "port" => 9501,

    "redis" => [
        "scheme" => "tcp",
        "host" => "0.0.0.0",
        "port" => 6380
    ],

    "avatar" => [
        "./images/avatar/1.jpg",
        "./images/avatar/2.jpg",
        "./images/avatar/3.jpg",
        "./images/avatar/4.jpg",
        "./images/avatar/5.jpg",
        "./images/avatar/6.jpg"
    ],

    "name" => [
        "科比",
        "庫里",
        "KD",
        "KG",
        "喬丹",
        "鄧肯",
        "格林",
        "湯普森",
        "伊戈達拉",
        "麥迪",
        "艾弗森",
        "卡哇伊",
        "保羅"
    ]
];

run.php

run();
總結(jié)

完整示例:聊天室

學完后發(fā)現(xiàn)生活中所謂的聊天室其實也不過如此,當然這只是簡單的demo,很多功能都沒有實現(xiàn),想進一步學習的話可以去github上找完整的項目進行深入學習

參考

swoole

PHP + Swoole 實現(xiàn)的簡單聊天室

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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/29836.html

相關(guān)文章

  • swoole 超簡單 構(gòu)建天室.資辭 群聊,組聊,單聊.

    摘要:今天來做一個簡單的聊天室支持換房間支持私信的寫的代碼有點渣里面有很多不是很好的地方畢竟我只是一個野生程序猿環(huán)境地址樣子差不多是這個樣子的我不想把代碼發(fā)到我的服務(wù)器上因為這個項目太小了很垃圾而且怕被攻擊這里有錄的一個演示視頻沒有廣告的你們可以 今天來做一個簡單的聊天室,支持換房間,支持私信的. 寫的代碼有點渣,里面有很多不是很好的地方.畢竟我只是一個野生程序猿. 環(huán)境: php7.0...

    Towers 評論0 收藏0
  • swoole 服務(wù)端120行代碼構(gòu)建一個websocket 天室.

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

    韓冰 評論0 收藏0
  • swoole簡單的天室demo(修正版)

    摘要:搜了一下,以前的很多類型文章,都是可能采集的,基本一樣,錯誤都一樣,所以自己寫了個,發(fā)來共享一下。 搜了一下,以前的很多類型文章,都是可能采集的,基本一樣,錯誤都一樣,所以自己寫了個,發(fā)來共享一下。 咱們可是抄襲文檔還有互聯(lián)網(wǎng)的,請確保你的服務(wù)器已經(jīng)安裝swoole1.7.7+版本擴展,9502端口未占用而且可以開啟 swoole文檔:https://wiki.swoole.com/w...

    Sourcelink 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<