Thinkphp5下使用WebSocket

参考手册:thinkphp5.1和workerman开发手册

下面开始:

使用composer下载:

composer require topthink/think-worker

下载下来后会有一些文件,重点看config里面的worker.php和worker_server.php。这两个是不同的监听配置,我使用的是worker_server.php

它的默认配置是这样的

return [
    // 扩展自身需要的配置
    'protocol'       => 'websocket', // 协议 支持 tcp udp unix http websocket text
    'host'           => '0.0.0.0', // 监听地址
    'port'           => 2346, // 监听端口
    'socket'         => 'hd.com:2346', // 完整监听地址
    'context'        => [], // socket 上下文选项
    'worker_class'   => '', // 自定义Workerman服务类名 支持数组定义多个服务
 
    // 支持workerman的所有配置参数
    'name'           => 'thinkphp',
    'count'          => 4,
    'daemonize'      => false,
    'pidFile'        => Env::get('runtime_path') . 'worker.pid',
 
    // 支持事件回调
    // onWorkerStart
    'onWorkerStart'  => function ($worker) {
 
    },
    // onWorkerReload
    'onWorkerReload' => function ($worker) {
 
    },
    // onConnect
    'onConnect'      => function ($connection) {
 
    },
    // onMessage
    'onMessage'      => function ($connection, $data) {
        $connection->send('你成功了');
    },
    // onClose
    'onClose'        => function ($connection) {
 
    },
    // onError
    'onError'        => function ($connection, $code, $msg) {
        echo "error [ $code ] $msgn";
    },
];

这时你打开命令行(cmd),切换到你项目根目录下

E:wamp64wwwhdv2018>E:wamp64binphpphp7.0.4php.exe   think   worker:server

因为我没有配置php的环境变量,所有就时候这种方式了。这时会看到这样的结果说明服务启动成功

打开chrome浏览器,按F12打开调试控制台,在Console一栏输入(或者把下面代码放入到html页面用js运行)

// 假设服务端ip为127.0.0.1
ws = new WebSocket("ws://127.0.0.1:2000");
ws.onopen = function() {
    alert("连接成功");
};
ws.onmessage = function(e) {
    alert("收到服务端的消息:" + e.data);
};

这是你会收到“你成功了”的字样。

接下来就是真正的开发流程了。

一般情况下我们会创建一个服务类(必须要继承 thinkworkerServer),然后设置属性和添加回调方法,这是我写的一个类

<?php
namespace appworker;
 
use thinkworkerServer;
use appcommonapiBaseApi;
 
class Worker extends Server
{
    protected $socket = 'http://0.0.0.0:2346';
 
    public function onMessage($connection,$data)
    {
    $data = explode('|', $data);
    switch ($data[0]) {
    case 'software_send_msg':
            if(!isset($data[1]) || empty($data[1])) {
            $list = json_encode(['result'=>'error','message'=>'参数为空']);
            }else{
            $account = $data[1];
            $uid = BaseApi::findData(8,2,[['user_login','=',$account]],'id');
 
            if($uid){
                list($data) = BaseApi::getListOne(16,[['user_id','=',$uid],['status','=',0]]);//16-software_send_msg
                if($data){
                    $list = [];
                    foreach ($data as $k => $v) {
                        $list[$k]['id'] = $v['id'];
                        $list[$k]['type'] = $v['type'];
                        $list[$k]['msg']  = $v['msg'];
                    }
             
                    $list = json_encode(['result'=>'success','data'=>json_encode($list)]);
                }else{
                    $list = json_encode(['result'=>'error', 'message'=>'数据为空']);
                }
                
            }else{
                $list = json_encode(['result'=>'error', 'message'=>'找不到该账号信息']);
            }
            }
            
    break;
 
    case 'software_send_msg2':
    $msg = 3333;
    break;
 
    default:
    $list = json_encode(['result'=>'error']);
    break;
    }
    $connection->send($list);//这里把数据发送给客户端
    }
}

这时要对worker_server.php进行修改,删掉之前的配置,只要加上这个即可

return [
    'worker_class'  =>  'appworkerWorker',
];

控制器:

public function ws()
{
        return $this->fetch(':ws');
}

模板:

<!DOCTYPE html>
<html xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <title>ThinkCMF WebSocket Demo</title>
    <script src="__STATIC__/js/jquery-2.0.3.min.js"></script>
</head>
<body>
<div id="app">
    软件模拟获取最新消息:
    <button class="get-msg">请求</button>
    <div class="return-msg">
    </div>
</div>
<script>
$(document).on('click','.get-msg',function(){
    ws = new WebSocket("ws://127.0.0.1:2346");
    //组织参数
    var param = new Array();
    param.push('software_send_msg');
    param.push('wydyhdzh');
    ws.onopen = function() {
        ws.send(param.join('|'));//向服务器返送信息
    };
    ws.onmessage = function(e) {//服务器返回信息
        var data = JSON.parse(e.data);
    
        if(data.result == 'success'){
            var list = JSON.parse(data.data);
            $('.return-msg').html(data.data);
        }
    };
})
</script>
</body>
</html>

 

效果如下: