国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

實戰 swoole【聊天室】

andycall / 2362人閱讀

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

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

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

代碼倉庫

實戰swoole【聊天室】

在線體驗

準備工作

需要先看初識swoole【上】,了解基本的服務端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;//調用外部的server
        // $server->connections 遍歷所有websocket連接用戶的fd,給所有用戶推送
        foreach ($server->connections as $fd) {
            $server->push($fd, $request->get["message"]);
        }
    });
$server->start();

詳解:

swoole_websocket_server 繼承自 swoole_http_server

設置了onRequest回調,websocket服務器也可以同時作為http服務器

未設置onRequest回調,websocket服務器收到http請求后會返回http 400錯誤頁面

如果想通過接收http觸發所有websocket的推送,需要注意作用域的問題,面向過程請使用global對swoole_websocket_server進行引用,面向對象可以把swoole_websocket_server設置成一個成員屬性

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

當WebSocket客戶端與服務器建立連接并完成握手后會回調此函數。

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

onOpen事件函數中可以調用push向客戶端發送數據或者調用close關閉連接

onOpen事件回調是可選的

function onMessage(swoole_websocket_server $server, swoole_websocket_frame $frame)

當服務器收到來自客戶端的數據幀時會回調此函數。

$frame 是swoole_websocket_frame對象,包含了客戶端發來的數據幀信息

onMessage回調必須被設置,未設置服務器將無法啟動

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

swoole_websocket_frame 屬性

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

$frame->data,數據內容,可以是文本內容也可以是二進制數據,可以通過opcode的值來判斷

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

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

聊天室服務端示例

目錄結構:

config

socket.php

src

websocket

Config.php

run.php

WebSocketServer.php 內存表版本

WsRedisServer.php redis版本

WebSocketServer.php 內存表版本

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"])]
        ];
        // 放入內存表
        $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) {
            // 自己不用發送
            if ($item["fd"] == $fd) {
                continue;
            }

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

    /**
     * 客戶端關閉的時候
     *
     * @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);
    }

    /**
     * 創建內存表
     */
    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();
        // 初始化,主要是服務端自己關閉不會清空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) {
            // 自己不用發送
            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"]);
            }
        }
    }

    /**
     * 客戶端關閉的時候
     *
     * @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();
總結

完整示例:聊天室

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

參考

swoole

PHP + Swoole 實現的簡單聊天室

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/29836.html

相關文章

  • swoole 超簡單 構建天室.資辭 群聊,組聊,單聊.

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

    Towers 評論0 收藏0
  • swoole 服務端120行代碼構建一個websocket 天室.

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

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

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

    Sourcelink 評論0 收藏0

發表評論

0條評論

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