首先通过 composer 安装Workerman
composer require topthink/think-worker=2.0.*
Thinkphp 5.1版本一定要加版本号在config文件夹下创建gateway_worker.php
<?php
return [
// 扩展自身需要的配置
'protocol' => 'websocket', // 协议 支持 tcp udp unix http websocket text
'host' => '0.0.0.0', // 监听地址
'port' => 2348, // 监听端口
'socket' => '', // 完整监听地址
'context' => [], // socket 上下文选项
'register_deploy' => true, // 是否需要部署register
'businessWorker_deploy' => true, // 是否需要部署businessWorker
'gateway_deploy' => true, // 是否需要部署gateway
// Register配置
'registerAddress' => '127.0.0.1:1236',
// Gateway配置
'name' => 'layim',
'count' => 1,
'lanIp' => '127.0.0.1',
'startPort' => 2000,
'daemonize' => false,
'pingInterval' => 30,
'pingNotResponseLimit' => 0,
'pingData' => '{"type":"ping"}',
// BusinsessWorker配置
'businessWorker' => [
'name' => 'layim',
'count' => 1,
'eventHandler' => 'app\index\controller\Events',
],
];
在application\index\controller文件夹下创建Events.php<?php
namespace app\index\controller;
use GatewayWorker\Lib\Gateway;
use Workerman\Worker;
use think\worker\Application;
class Events
{
public static $user = [];
public static $uuid = [];
/**
* onWorkerStart 事件回调
* 当businessWorker进程启动时触发。每个进程生命周期内都只会触发一次
*
* @access public
* @param \Workerman\Worker $businessWorker
* @return void
*/
public static function onWorkerStart(Worker $businessWorker){
}
public static function onConnect($client_id){
//向客户端client_id发送$send_data数据。如果client_id对应的客户端不存在或者不在线则自动丢弃发送数据
Gateway::sendToClient($client_id, json_encode(array(
'type' => 'init',
'client_id' => $client_id,
)));
}
/**
* 有消息时触发该方法
* @param int $client_id 发消息的client_id
* @param mixed $message 消息
* @return void
*/
public static function onMessage($client_id,$message)
{
/*监听事件,需要把客户端发来的json转为数组*/
$data = json_decode($message, true);
switch ($data['type']) {
//当有用户上线时
case 'reg':
//绑定uid 用于数据分发
Gateway::bindUid($client_id, $data['uid']);
self::$user[$data['uid']] = $client_id;
self::$uuid[$data['uid']] = $data['uid'];
//给当前客户端 发送当前在线人数,以及当前在线人的资料
$reg_data['uuser'] = self::$uuid;
$reg_data['num'] = count(self::$user);
$reg_data['type'] = "reguser";
Gateway::sendToClient($client_id, json_encode($reg_data));
//将当前在线用户数量,和新上线用户的资料发给所有人 但把排除自己,否则会出现重复好友
$all_data['type'] = "addList";
$all_data['content']['uid']=$data['uid'];
$all_data['content']['type'] = 'friend';
$all_data['content']['groupid'] = 2;
$all_data['num'] = count(self::$user);
Gateway::sendToAll(json_encode($all_data));
break;
case 'online':
Gateway::sendToAll(json_encode($data));
break;
case 'chatMessage':
//处理聊天事件
$msg['username'] = $data['content']['mine']['username'];
$msg['avatar'] = $data['content']['mine']['avatar'];
$msg['id'] = $data['content']['mine']['id'];
$msg['content'] = $data['content']['mine']['content'];
$msg['type'] = $data['content']['to']['type'];
$chatMessage['type'] = 'getMessage';
$chatMessage['content'] = $msg;
//处理单聊
if ($data['content']['to']['type'] == 'friend') {
if (isset(self::$uuid[$data['content']['to']['id']])) {
Gateway::sendToUid(self::$uuid[$data['content']['to']['id']], json_encode($chatMessage));
} else {
//处理离线消息
$noonline['type'] = 'noonline';
Gateway::sendToClient($client_id, json_encode($noonline));
}
} else {
//处理群聊
$chatMessage['content']['id'] = $data['content']['to']['id'];
Gateway::sendToAll(json_encode($chatMessage), '', $client_id);
}
break;
}
}
/**
* 当用户断开连接时触发的方法
* @param integer $client_id 断开连接的客户端client_id
* @return void
*/
public static function onClose($client_id)
{
//有用户离线时触发 并推送给全部用户
$data['type'] = "out";
$data['id'] = array_search($client_id, self::$user);
unset(self::$user[$data['id']]);
unset(self::$uuid[$data['id']]);
$data['num'] = count(self::$user);
Gateway::sendToAll(json_encode($data));
}
/**
* onWebSocketConnect 事件回调
* 当客户端连接上gateway完成websocket握手时触发
*
* @param integer $client_id 断开连接的客户端client_id
* @param mixed $data
* @return void
*/
public static function onWebSocketConnect($client_id, $data){
}
/**
* onWorkerStop 事件回调
* 当businessWorker进程退出时触发。每个进程生命周期内都只会触发一次。
*
* @param \Workerman\Worker $businessWorker
* @return void
*/
public static function onWorkerStop(Worker $businessWorker){
}
}
在命令行运行php think worker:gateway
LayIM代码自行购买var socket = new WebSocket('自己的地址');
//连接成功时触发
socket.onopen = function() {
socket.send(JSON.stringify({
type: 'reg', //随便定义,用于在服务端区分消息类型
uid: layui.sessionData(setter.tableName)[setter.request.tokenName]
}));
};
//监听发送消息
layim.on('sendMessage', function(data) {
socket.send(JSON.stringify({
type: 'chatMessage', //随便定义,用于在服务端区分消息类型
content: data
}));
console.log(data);
});
//监听收到的聊天消息,假设你服务端emit的事件名为:chatMessage
socket.onmessage = function(res) {
res = JSON.parse(res.data);
console.log(res);
if(res.type === 'init') {
client_id = res.client_id;
} else if(res.type === 'addList') {
layim.setFriendStatus(res.content.uid, 'online');
} else if(res.type === 'reguser'){
console.log(res.uuser);
for (let i in res.uuser) {
layim.setFriendStatus(res.uuser[i], 'online');
}
}else if(res.type==='getMessage'){
layim.getMessage(res.content); //res.data即你发送消息传递的数据(阅读:监听发送的消息)
}else if(res.type==='out'){
layim.setFriendStatus(res.id, 'offline');
}else if(res.type==='online'){
layim.setFriendStatus(res.uid, res.status);
}else if(res.type=='noonline'){
layim.setChatStatus('<span style="color:#FF5722;">离线</span>');
}else{
}
};