前言
本文纯属经验备注,有许多地方未进行测试,请勿照搬,仅供参考。
之前专门花了几天时间测试了websocket,当时只记得踩了许多坑,但是没有对测试流程进行记录,导致长时间未使用从而无从下手。
今天就简单记录一下使用流程。
环境介绍
- php7.4+
- linux
- nginx
- thinkphp5.1
- workerman
流程
1、安装长连接框架:composer require workerman/gateway-worker 2、配置基本参数 配置为文件为 config/gateway_worker.php(必须使用对应命令才能启动) 配置端口startPort,pingData,eventHandler,其它默认就好 eventHandler配置为appindexlogiceventsEvents.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://boomim.playone.cn/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' => ' hinkworkerEvents', //这里配置事件监听后的业务逻辑处理代码,Events.php类 'eventHandler' => 'appindexlogiceventsEvents', ], ];
Events类(定制业务逻辑)
<?php namespace appindexlogicevents; use appindexlogicBaselogic; use GatewayWorkerLibGateway; use thinkworkerApplication; use wanghuageneral_utility_tools_php oolTools; use WorkermanWorker; /** * 事件监听后的业务逻辑(自由定制) */ class Events extends hinkworkerEvents { /** * onWorkerStart 事件回调 * 当businessWorker进程启动时触发。每个进程生命周期内都只会触发一次 * * @access public * @param WorkermanWorker $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 "); Tools::log_to_write_text(['断开连接.client_id:'.$client_id]); } /** * onWorkerStop 事件回调 * 当businessWorker进程退出时触发。每个进程生命周期内都只会触发一次。 * * @param WorkermanWorker $businessWorker * @return void */ public static function onWorkerStop(Worker $businessWorker) { //echo "WorkerStop "; Tools::log_to_write_text(['businessWorker进程退出时触发。每个进程生命周期内都只会触发一次.',$businessWorker]); } }
END