1:首先通过 composer 安装
composer require topthink/think-worker=2.0.*
2:配置(注意我这边就配置一个worker_server.php)
配置如下
<?php return [ 'worker_class' => 'app\http\Worker', ];
解释:命令
如图
3:创建文件
创建 worker.php 文件 注意 app\http\Worker(命名空间 可以根据自己的业务需求更开 建议先别更改 等测试通过在进行更改)
<?php namespace app\http; use think\worker\Server; class Worker extends Server { protected $socket = 'websocket://0.0.0.0:2346'; protected $uidConnections = []; protected $HEARTBEAT_TIME = '300'; /** * 收到信息 * @param $connection * @param $data */ public function onMessage($connection, $data) { // 给connection临时设置一个lastMessageTime属性,用来记录上次收到消息的时间 $connection->lastMessageTime = time(); $data = json_decode($data,true); if(empty($data)){ } switch($data['type']){ case 'login': // 保存该用户的输送数据 $this->uidConnections[$data['uid']] = $connection; $connection->send('所有用户等会收到的信息'); $this->send_uid($data['uid'],"通过保存uid:{$data['uid']}为给你发的信息"); break; case 'sendMessage': // 发送所有消息 $this->send_all($data['message'],$data['uid']); break; case 'sendUser' : // 发送单个消息 $this->send_uid($data['uid'],$data['message']); break; } } /** * 当连接建立时触发的回调函数 * @param $connection */ public function onConnect($connection) { $connection->send('已建立连接'); } /** * 当连接断开时触发的回调函数 * @param $connection */ public function onClose($connection) { $connection->send('连接断开'); } /** * 当客户端的连接上发生错误时触发 * @param $connection * @param $code * @param $msg */ public function onError($connection, $code, $msg) { echo "error $code $msg\n"; } /** * 每个进程启动 * @param $worker */ public function onWorkerStart($worker) { // 开启一个内部端口,方便内部系统推送数据,Text协议格式 文本+换行符 $inner_text_worker = new \Workerman\Worker('Text://0.0.0.0:56781'); $inner_text_worker->onMessage = function ($connection, $buffer){ $buffer = json_decode($buffer,false); switch($buffer->type){ case 'sendMessage' : $res = $this->send_all($buffer->message); break; case 'sendUser' : $res = $this->send_uid($buffer->uid,$buffer->message); break; default: $res = $this->send_all('成功'); } $connection->send($res ? 'ok' : 'fail'); }; $inner_text_worker->listen(); #下面是心跳 // Timer::add(5, function()use($worker){ // $time_now = time(); // foreach($worker->connections as $connection) { // // 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间 // if (empty($connection->lastMessageTime)) { // $connection->lastMessageTime = $time_now; // continue; // } // $diff_time = $time_now - $connection->lastMessageTime; // // $msg = '距离上次通话已经过去'.$diff_time.'秒'; // $connection->send(""); // // 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接 // if ($time_now - $connection->lastMessageTime > $this->HEARTBEAT_TIME) { // $connection->close(); // } // } // }); } public function send_uid($uid,$message) { if(isset($this->uidConnections[$uid])){ // 获取之前用户的链接 $conn = $this->uidConnections[$uid]; //echo $uid.PHP_EOL; $conn->send($message); return true; } return false; } public function send_all($message,$uid = '') { foreach($this->uidConnections as $conn){ if(!empty($uid)){ //不推送给自己 if($conn != $this->uidConnections[$uid]){ $conn->send($message); } }else{ $conn->send($message); } } return true; } }
4:启动
php think worker:server
启动成功
5:搭建WebSocket(html)vue和uni-app原理都差不多
<script src='/static/socket.io.js'></script> <div onclick="send()"></div> <script> var socket = new WebSocket("wss://o2onew.ccfqkj.com/wss"); socket.onopen = function(event) { socket.send( JSON.stringify({ type: "login", uid: 1, }) ); // 发送一个初始化消息 // socket.send('1'); }; socket.onmessage = function(event) { console.log('收到消息',event.data); }; function send() { socket.send(JSON.stringify({ type: "sendMessage", uid: 2, message:"1221" })); } </script>
socket地址(最好下载本地在运行)
访问html
6:服务发送消息到用户端
$type = input('type','sendMessage'); $msg = input('msg','hello word'); $client = stream_socket_client('tcp://tui.ccfqkj.com:56781', $errno, $errmsg, 1); // 推送的数据,包含用户,表示是给这个用户推送 $data = array('uid'=>'1', 'message'=>$msg,'type'=>$type); // 发送数据,注意5678端口是Text协议的端口,Text协议需要在数据末尾加上换行符 fwrite($client, json_encode($data)."\n"); // 读取推送结果 echo fread($client, 8192);
发送成功
发送失败
一般发送失败都是发送协议不对
服务端发送消息html接收
至此就全完成了