前言
本文纯属经验备注,有许多地方未进行测试,请勿照搬,仅供参考。
之前专门花了几天时间测试了websocket,当时只记得踩了许多坑,但是没有对测试流程进行记录,导致长时间未使用从而无从下手。
今天就简单记录一下使用流程。
环境介绍
- php7.4+
- linux
- nginx
- thinkphp5.1
- workerman
流程
1、安装长连接框架:composer require workerman/gateway-worker
2、配置基本参数配置文件为 config/gateway_worker.php(必须使用对应命令才能启动)配置端口startPort,pingData,eventHandler,其它默认就好eventHandler配置为app\index\logic\events\Events.php类,用于处理监听后的业务逻辑
3、启动服务唯一启动命令:php think worker:gateway
4、nginx服务配置以支持/wss方式访问参考配置:location /wss{proxy_pass http://127.0.0.1:2000;proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "Upgrade";proxy_set_header X-Real-IP $remote_addr;}
5、JavaScript客户端建立连接并访问ws = new WebSocket("wss://bootest.playtest.top/wss");//这种访问方式需要nginx配置ws.onopen = function() {alert("连接成功");ws.send('hello,thinkphp');alert("给服务端发送一个字符串:hello,thinkphp");
详细配置参考(gateway_worker.php)
//gateway_worker.php 文件配置
<?php
// +----------------------------------------------------------------------
// | Workerman设置 仅对 php think worker:gateway 指令有效
// +----------------------------------------------------------------------
return [/** 【长连接使用此配置,启动命令: php think worker:gateway 】 */// 扩展自身需要的配置'protocol' => 'websocket', // 协议 支持 tcp udp unix http websocket text'host' => '0.0.0.0', // 监听地址'port' => 2000, // 监听端口'socket' => '', // 完整监听地址'context' => [], // socket 上下文选项'register_deploy' => true, // 是否需要部署register'businessWorker_deploy' => true, // 是否需要部署businessWorker'gateway_deploy' => true, // 是否需要部署gateway// Register配置'registerAddress' => '127.0.0.1:1236',// Gateway配置'name' => 'thinkphp','count' => 1,'lanIp' => '127.0.0.1','startPort' => 1350,'daemonize' => false,'pingInterval' => 30,'pingNotResponseLimit' => 0,//这里根据自己需要配置,不一定使用json'pingData' => '{"code":"200","msg":"ok","action":"ping"}',// BusinsessWorker配置'businessWorker' => ['name' => 'BusinessWorker','count' => 1,
// 'eventHandler' => '\think\worker\Events',//这里配置事件监听后的业务逻辑处理代码,Events.php类'eventHandler' => 'app\index\logic\events\Events',],];
Events类(定制业务逻辑)
上面eventHandler类对应的文件
<?phpnamespace app\index\logic\events;use app\index\logic\Baselogic;
use GatewayWorker\Lib\Gateway;
use think\worker\Application;
use wanghua\general_utility_tools_php\tool\Tools;
use Workerman\Worker;/*** 事件监听后的业务逻辑(自由定制)*/
class Events extends \think\worker\Events
{/*** onWorkerStart 事件回调* 当businessWorker进程启动时触发。每个进程生命周期内都只会触发一次** @access public* @param \Workerman\Worker $businessWorker* @return void*/public static function onWorkerStart(Worker $businessWorker){$app = new Application;$app->initialize();}/*** onConnect 事件回调* 当客户端连接上gateway进程时(TCP三次握手完毕时)触发** @access public* @param int $client_id* @return void*/public static function onConnect($client_id){//一个连接只触发一次Tools::log_to_write_text('客户端完成TCP握手');$res = Tools::set_ok('ok','onConnect',['client_id'=>$client_id]);Gateway::sendToCurrentClient(json_encode($res,JSON_UNESCAPED_UNICODE));}/*** onWebSocketConnect 事件回调* 当客户端连接上gateway完成websocket握手时触发** @param integer $client_id 断开连接的客户端client_id* @param mixed $data {"get":[],"server":{"REQUEST_METHOD":"GET","REQUEST_URI":"/wss","SERVER_PROTOCOL":"HTTP/1.1","HTTP_UPGRADE":"websocket","HTTP_CONNECTION":"Upgrade","HTTP_X_REAL_IP":"183.227.89.107","HTTP_HOST":"127.0.0.1:2000","SERVER_NAME":"127.0.0.1","SERVER_PORT":"2000","HTTP_PRAGMA":"no-cache","HTTP_CACHE_CONTROL":"no-cache","HTTP_USER_AGENT":"wechatdevtools desktopapp appservice port/62717 token/589065e467011760c777411fca2cd0aa runtime/2 MicroMessenger","HTTP_ORIGIN":"https://boomim.playone.cn","HTTP_SEC_WEBSOCKET_VERSION":"13","HTTP_ACCEPT_ENCODING":"gzip, deflate, br","HTTP_ACCEPT_LANGUAGE":"zh-CN,zh;q=0.9","HTTP_CONTENT_TYPE":"application/json","HTTP_REFERER":"https://servicewechat.com/wx55e10fb2834803d5/devtools/page-frame.html","HTTP_SEC_WEBSOCKET_KEY":"uWOWC1AZahJOpS18hN3ZHA==","HTTP_SEC_WEBSOCKET_EXTENSIONS":"permessage-deflate; client_max_window_bits","QUERY_STRING":""},"cookie":[]}* @return void*/public static function onWebSocketConnect($client_id, $data){// var_export($data);//对应客户端打开连接, 一个连接只触发一次Tools::log_to_write_text(['客户端打开了websocket连接',$data]);//$res = Tools::set_ok('ok',['client_id'=>$client_id,'msg'=>'客户端打开连接时,发送到服务端的消息:','data'=>$data]);////Gateway::sendToCurrentClient(json_encode($res,JSON_UNESCAPED_UNICODE));}/*** onMessage 事件回调* 当客户端发来数据(Gateway进程收到数据)后触发** @access public* @param int $client_id* @param mixed $data* @return void*/public static function onMessage($client_id, $data){Tools::log_to_write_text(['客户端发来数据(Gateway进程收到数据).client_id:'.$client_id,$data]);//$res = Tools::set_ok('ok',['client_id'=>$client_id,'msg'=>'你发来的消息我接收到了:',$client_id=>$data]);//Gateway::sendToClient($client_id,json_encode($res,JSON_UNESCAPED_UNICODE));}/*** onClose 事件回调 当用户断开连接时触发的方法** @param integer $client_id 断开连接的客户端client_id* @return void*/public static function onClose($client_id){//GateWay::sendToAll("client[$client_id] logout\n");Tools::log_to_write_text(['断开连接.client_id:'.$client_id]);}/*** onWorkerStop 事件回调* 当businessWorker进程退出时触发。每个进程生命周期内都只会触发一次。** @param \Workerman\Worker $businessWorker* @return void*/public static function onWorkerStop(Worker $businessWorker){//echo "WorkerStop\n";Tools::log_to_write_text(['businessWorker进程退出时触发。每个进程生命周期内都只会触发一次.',$businessWorker]);}
}
END