^

websocket开发笔记

做了一个CTF平台,遇到了后台公告及时提醒的功能。如果使用传统轮询,多用户会直接让后端卡死,所以需要研究下ws。

主流的框架有wokerman、swoole,这里选择装wokerman。

安装

composer require topthink/think-worker

更换国内镜像会快点 但这里是一个坑点 用阿里云的显示下载404 用其他的 显示证书错误

只有腾讯可以 还是腾讯牛逼

composer config -g repos.packagist composer https://mirrors.cloud.tencent.com/composer/

使用WSS

由于网站使用了https,则无法使用ws来进行通信链接。

需要使用nginx做流量转发

规则如下:

1.前端使用wss://domain/uri 进行连接

2.nginx配置如下

    location /uri {
        proxy_pass http://domain:port; 
        proxy_read_timeout 60s;
        proxy_http_version 1.1;
        proxy_set_header X-Client-IP $remote_addr;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'Upgrade';
    }

3.测试demo

<html><head><meta charset="utf-8" /><title>网页版群聊</title></head><body><script>
            ws = new WebSocket("wss://ctf.happysec.cn/websocket");
            ws.onopen = function() {
                console.log("连接成功");
                ws.send('tom');
                console.log("给服务端发送一个字符串:tom");
            };
            ws.onmessage = function(e) {
                console.log("收到服务端的消息:" + e.data);
            };</script></body></html>


4.tp6 定义控制器

<?php

namespace app\index\controller;
use think\worker\Server;
use think\facade\Session;

class Push extends Server{

    protected $socket = 'websocket://0.0.0.0:2345';

    public function onMessage($connection, $data)
    {
        $connection->send($data);
    }

    /**
     * 当连接建立时触发的回调函数
     * @param $connection
     */
    public function onConnect($connection)
    {
        $connection->send("连接成功");
    }

    /**
     * 当连接断开时触发的回调函数
     * @param $connection
     */
    public function onClose($connection)
    {
        
    }

    /**
     * 当客户端的连接上发生错误时触发
     * @param $connection
     * @param $code
     * @param $msg
     */
    public function onError($connection, $code, $msg)
    {
        echo "error $code $msg\n";
    }

    /**
     * 每个进程启动
     * @param $worker
     */
    public function onWorkerStart($worker)
    {

    }
    
}

在wokerman_server注册服务

'worker_class'   => 'app\index\controller\Push', // 自定义Workerman服务类名 支持数组定义多个服务

运行wokerman服务端 

php think worker:server



看了一堆文档手册 觉得思维很混乱 我觉得还是需要具体到业务上去 也就是我需要实现什么样的业务逻辑

(全体客户端推送消息)

1.后端编写通知 notification模块的crud逻辑

2.对c的逻辑重写 添加短信息的同时补充同时触发消息推送 可以用访问api的方式触发

3.wokerman对所有链接客户端发送消息 并通过js弹窗提示

(定向推送短消息)

1.给用户添加一个新方法 发送短信息

2.弹窗显示文本

3.使用workerman对该uid的用户推送消息

4.用户如果登录 并持续长链接 就弹窗提醒消息

我们可以做第一个功能 crud的模块已经完成了 接着就是做如果推送消息给所有链接用户

然后 学了一下午wokerman 发现 我需要实现的功能 就是gatewaywoker而已 只是一个中转 不需要处理业务逻辑

浪费了一下午

重新运行 php think worker:gateway

nginx中的wss也重新绑定端口 重新注册

 // 当有客户端连接时,将client_id返回,让mvc框架判断当前uid并执行绑定
    public static function onConnect($client_id)
    {
        Gateway::sendToClient($client_id, json_encode(array(
            'type'      => 'init',
            'client_id' => $client_id
        )));
    }

    // GatewayWorker建议不做任何业务逻辑,onMessage留空即可
    public static function onMessage($client_id, $message)
    {

    }

 当收到链接请求的时候 进行用户id 和clientid绑定 作为第二个功能需要

 sendall不需要进行绑定 会群发消息 但是 没登录的用户也会收到消息提示

所以需要把用户统一加到一个组里去 但是暂时先不写


实现了一开始的设想