美文网首页
laravel集成swoole实现wss协议websocket消

laravel集成swoole实现wss协议websocket消

作者: 耍帅oldboy | 来源:发表于2022-09-20 13:40 被阅读0次

背景介绍,后端使用laravel8框架,需求扫码登录,扫码成功服务端推送消息给js,js主动获取新,跳转成功页面,扫码登录的业务在这里不详细叙述,有空再写。主要是还需要用的swoole/table的功能,内容太多,本次主要介绍laravel集成swoole实现websocket实现的过程,并且支持wss协议

1、安装swoole版本4.8.11,(5.0以上版本编译失败)

wget https://github.com/swoole/swoole-src/archive/refs/tags/v4.8.11.zip
mv v4.8.11.zip swoole-v4.8.11.zip
unzip swoole-v4.8.11.zip 
cd swoole-
cd swoole-src-4.8.11/
phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make && make install
vim /usr/local/php/etc/php.ini
#添加 extension=swoole.so
#重启php-fpm
/etc/init.d/php-fpm restart
#查看扩展是否安装好
php -m | grep swoole

2、在laravel的根目录php artisan make:commad websocket创建websocket命令

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class Websocket extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'websocket';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'this is websocket';

    /**
     * Create a new command instance.
     *
     * @return void
     */

    private $ws;

    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $this->start();
    }

    public function start() {
        //创建WebSocket Server对象,监听0.0.0.0:9501端口,,通过nginx方向代理支持wss
        $this->ws = new \Swoole\WebSocket\Server('127.0.0.1', 9501);
        //监听WebSocket连接打开事件
        $this->ws->on('Open', function ($ws, $request) {
            $ws->push($request->fd, "hello, welcome{$request->fd}\n");
        });

        //监听WebSocket消息事件
        $this->ws->on('Message', function ($ws, $frame) {
            echo "Message: {$frame->data}\n";
            #可以绑定fd和token关系,使用swoole/table
            $ws->push($frame->fd, "server: {$frame->data}");
        });

        $this->ws->on('request', function ($request, $response) {
            $msg = $request->post['message'];
            // $server->connections 遍历所有websocket连接用户的fd,给所有用户推送
            // 可以通过swoole/table绑定fd->token关系反向找到fd,从而推送给指定用户
            foreach ($this->ws->connections as $fd) {
                // 需要先判断是否是正确的websocket连接,否则有可能会push失败
                //广播推送
                if ($this->ws->isEstablished($fd)) {
                    $this->ws->push($fd, $msg);
                    $this->info("client is PushMessage\n".$msg);
                }
            }

        });

        //监听WebSocket连接关闭事件
        $this->ws->on('Close', function ($ws, $fd) {
            echo "client-{$fd} is closed\n";
        });

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

3、启动websocket服务端 php artisan websokct

生产环境使用supervisord配置如下

vim /etc/supervisord.conf
[program:websocket]
command=/bin/php artisan websocket
numprocs=1
directory=/home/wwwroot/xxx.xxx.com
user=www
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/supervisor/websocket.log
#更新配置命令
supervisorctl update

4、nginx反向代理websocket,支持wss协议

server
    {
        listen 443 ssl http2;
        #listen [::]:443 ssl http2;
        server_name xxx.xxx.com ;
        index index.html index.htm index.php default.html default.htm default.php;

        ssl_certificate /usr/local/nginx/conf/ssl/xxx.xxx.com/fullchain.cer;
        ssl_certificate_key /usr/local/nginx/conf/ssl/xxx.xxx.com/xxx.xxxcom.key;
        ssl_session_timeout 5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;
        ssl_ciphers "TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5";
        ssl_session_cache builtin:1000 shared:SSL:10m;
        ssl_dhparam /usr/local/nginx/conf/ssl/dhparam.pem;

        #nginx转发websocket服务端处理
        location /websocket {
             #websocket服务端监听的地址和端口
             proxy_pass http://127.0.0.1:9501;
             proxy_read_timeout 300s;
             proxy_send_timeout 300s;
         
             proxy_set_header Host $host;
             proxy_set_header X-Real-IP $remote_addr;
             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         
             proxy_http_version 1.1;
             proxy_set_header Connection "upgrade";
             proxy_set_header Upgrade $http_upgrade;
        }

5、js端代码

         url = `wss://xxx.xxx.com/websocket`;

        // 打开一个websocket
        let websocket = new WebSocket(url);
        // 建立连接
        websocket.onopen = () => {
          // 发送数据
          websocket.send("发送数据");
          console.log("websocket发送数据中");
        };
        // 客户端接收服务端返回的数据
        websocket.onmessage = evt => {
          console.log("websocket返回的数据:", evt);
        };
        // 发生错误时
        websocket.onerror = evt => {
          console.log("websocket错误:", evt);
        };
        // 关闭连接
        websocket.onclose = evt => {
          console.log("websocket关闭:", evt);
        };

6、curl发送post发送给websocket服务端onRequest(处理消息),websocket服务端收到消息,通过websocket再推送给客户端

public function curl($data)
{
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, "http://127.0.0.1:9501");
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_HEADER, 1);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_exec($curl);
        curl_close($curl);
}
$data['message'] = '主动推送消息'.date("Y-m-d H:i:s");
curl($data);

7、js收到消息如下图

image.png

相关文章

网友评论

      本文标题:laravel集成swoole实现wss协议websocket消

      本文链接:https://www.haomeiwen.com/subject/cybportx.html