zoukankan      html  css  js  c++  java
  • swoole websocket服务推送

    用过workerman, 两个字"好用",对于swoole最近有时间也研究研究

    swoole的websocket 很好实现

    如官网 https://wiki.swoole.com/wiki/page/479.html

    ws_server.php

    //创建websocket服务器对象,监听0.0.0.0:9502端口
    $ws = new swoole_websocket_server("0.0.0.0", 9502);
    
    //监听WebSocket连接打开事件
    $ws->on('open', function ($ws, $request) {
        var_dump($request->fd, $request->get, $request->server);
        $ws->push($request->fd, "hello, welcome
    ");
    });
    
    //监听WebSocket消息事件
    $ws->on('message', function ($ws, $frame) {
        echo "Message: {$frame->data}
    ";
        $ws->push($frame->fd, "server: {$frame->data}");
    });
    
    //监听WebSocket连接关闭事件
    $ws->on('close', function ($ws, $fd) {
        echo "client-{$fd} is closed
    ";
    });
    
    $ws->start();

    运行程序

    php ws_server.php

    客户端 a.html

    var wsServer = 'ws://127.0.0.1:9502';
    var websocket = new WebSocket(wsServer);
    websocket.onopen = function (evt) {
        console.log("Connected to WebSocket server.");
    };
    
    websocket.onclose = function (evt) {
        console.log("Disconnected");
    };
    
    websocket.onmessage = function (evt) {
        console.log('Retrieved data from server: ' + evt.data);
    };
    
    websocket.onerror = function (evt, e) {
        console.log('Error occured: ' + evt.data);
    };

    ok了!

    现在我们看到的是客户端发送信息,服务器应答并返回数据

    那我们现在要的是服务器主动发送信息

    有三个办法:

    1.使用swoole的定时器,定时发送,可通过syc从数据库获取数据逻辑判断后push发送给客户端

    2.使用swoole中自带框架

    这个方法和方法3原理是一样的,就是需要后台主动推送的时候,模拟一个客户端发送消息,可以是CLI的脚本,也可以是php的CURL请求

    https://github.com/matyhtf/framework/blob/master/libs/Swoole/Client/WebSocket.php

    github下载地址: https://github.com/matyhtf/framework

    <?php
    define('DEBUG', 'on');
    define("WEBPATH", str_replace("\", "/", __DIR__));
    require __DIR__ . '/framework-master/libs/lib_config.php';
    $client = new SwooleClientWebSocket('127.0.0.1', 9502);
    if (!$client->connect()) {
        echo "connect to server failed.
    ";
        exit;
    }
    
      $client->send("我是PHP-client端,发来的消息");  # 客户端可以看到

    3.设置onRequest回调

    用过workerman的都知道,workerman中就有这个获取http的get,post 数据并sendto客户端,在这里swoole也可以实现

    https://wiki.swoole.com/wiki/page/397.html

    swoole_websocket_server 继承自 swoole_http_server

      • 设置了onRequest回调,websocket服务器也可以同时作为http服务器
      • 未设置onRequest回调,websocket服务器收到http请求后会返回http 400错误页面
      • 如果想通过接收http触发所有websocket的推送,需要注意作用域的问题,面向过程请使用“global”对swoole_websocket_server进行引用,面向对象可以把swoole_websocket_server设置成一个成员属性

    代码如下

    ser.php

    <?php
    
    class MyWebsocket {
    
        private $server;
        private $fid=[];
        # run()
        public function toRun() {
            $this->server = new swoole_websocket_server("0.0.0.0", 9502, SWOOLE_BASE, SWOOLE_SOCK_TCP); //SWOOLE_SSL  需要ssl才加
            #监听WebSocket连接打开事件
            $this->server->on('open', function ($server, $request) {
                $this->server->push($request->fd, "hello, welcome ID:{$request->fd}
    ");
                $this->fid[]=$request->fd;   # $request->fd fd 
            });
            #监听WebSocket消息事件
            $this->server->on('message', function ($server, $frame) {   #$frame->data 消息内容
                $msg = 'from' . $frame->fd . ":{$frame->data}
    ";
                foreach ($this->fid as $fd) {
                    $server->push($fd, $msg);
                }
            });
    
            //监听WebSocket连接关闭事件
            $this->server->on('close', function($ws, $fd) {
            $fd_key = array_search($fd, $this->fid ? $this->fid : []);
            $key_zero = isset($this->fid[0]) && $this->fid[0] == $fd ? TRUE : FALSE;  # key=0 
            if ($fd_key || $key_zero) {
                unset($this->fid[$fd_key]);
            }
            echo "client-{$fd} is closed
    ";
        });
    
            #onRequest回调    http://127.0.0.1:9502/?sendto=1,20,3&message=%E4%BD%A0%E5%A5%BD
            $this->server->on('request', function ($req, $respone) {
                # get 两个参数, userid ","  发送消息
                $list=[];
                if (isset($req->get['sendto']) && isset($req->get['message'])) {
                    $user = explode(',', $req->get['sendto']);
                    $list = array_intersect($this->fid, $user);
                    if (!empty($list)) {
                        foreach ($list as $fd) {
                            $this->server->push($fd, $req->get['message']);
                        }
                    }
                }
                $total= count($this->fid);
                $sendSum= count($list);
                  $respone->end("Current fid:{$respone->fd},  OnLine:{$total}, Send:{$sendSum}");    
                
            });
    
            $this->server->start();
        }
    
       
    
    }
    
    $app = new MyWebsocket();
    $app->toRun();

    客户端html

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>Title</title>
        </head>
        <body>
            <div id="msg"></div>
            <input type="text" id="text">
            <input type="submit" value="发送数据" onclick="sending()">
        </body>
        <script>
            var msg = document.getElementById("msg");
            var wsServer = 'ws://127.0.0.1:9502';
            //调用websocket对象建立连接:
            //参数:ws/wss(加密)://ip:port (字符串)
            var websocket = new WebSocket(wsServer);
            //onopen监听连接打开
            websocket.onopen = function (evt) {
                //websocket.readyState 属性:
                /*
                 CONNECTING    0    The connection is not yet open.
                 OPEN    1    The connection is open and ready to communicate.
                 CLOSING    2    The connection is in the process of closing.
                 CLOSED    3    The connection is closed or couldn't be opened.
                 */
                console.log(websocket.readyState);
            };
    
            function sending() {
                var text = document.getElementById('text').value;
                document.getElementById('text').value = '';
                //向服务器发送数据
                websocket.send(text);
            }
            //监听连接关闭
            websocket.onclose = function (evt) {
                msg.innerHTML+="Disconnected<br>";
            };
    
            //onmessage 监听服务器数据推送
            websocket.onmessage = function (evt) {
                msg.innerHTML += evt.data + '<br>';
                console.log('Retrieved data from server: ' + evt.data);
            };
            //监听连接错误信息
            websocket.onerror = function (evt, e) {
                console.log('Error occured: ' + evt.data);
            };
    
        </script>
    </html>

    运行

    php ser.php 

  • 相关阅读:
    margin+absolute布局:右栏固定主内容自适应 demo
    localForage——轻松实现 Web 离线存储
    迷你MVVM框架 avalonjs 1.2.6发布
    收起.NET程序的dll来
    从锅炉工到AI专家 ---- 系列教程
    DevExpress中实现GridControl的分页功能
    树莓派 ---- 个人总结
    树莓派安装内网穿透版花生壳服务
    winform 多线程中ShowDialog()模式窗口无效的解决办法
    局域网匿名访问共享文件
  • 原文地址:https://www.cnblogs.com/dcb3688/p/4608056.html
Copyright © 2011-2022 走看看