thinkphp5下使用WebSocket

最近有个项目需求是这样的:软件端会向服务器发送请求,获取一些信息。然后对获取过来的信息进行处理,再返回信息的id

方式一:软件端那边调用接口,一分钟请求一次。

问题出现:如果有几万个人同时用软件,就会产生大量的http请求,导致负载过高。因此需求考虑到第二种方式。

方式二:使用WebSocket,进行一次长连接,这样就减少了大量的请求。

因为对于webscoket要求不高,因此就选择了Workerman,这也是thinkphp5封装好的扩展,直接下载下来用。

参考手册: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 ] $msg\n";
    },
];

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

E:\wamp64\www\hd\v2018>E:\wamp64\bin\php\php7.0.4\php.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);
};

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

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

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

<?php
// +----------------------------------------------------------------------
// | websocket
// +----------------------------------------------------------------------
// | Author: myh
// +----------------------------------------------------------------------

namespace app\worker;

use think\worker\Server;
use app\common\api\BaseApi;

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'  =>  'app\worker\Worker',
];

控制器:

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>

整个流程就是这样,不明白可以留言

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值