tp框架和fastadmin引用websocket,使用workerman对websocket的封装及使用(中小型项目在线聊天后台搭建)
windows下需要运行(tp5手册:https://www.kancloud.cn/manual/thinkphp5/235128)cmd 项目中到public目录下运行php server.php start-测试环境 生产环境 后面加-d。application下新建worker目录及worker.php文件。alert(“收到服务端的消息:” + e.data);alert(“收到服务端的
第一步:cmd 到项目根目录运行
1 :composer require topthink/think-worker=1.0.* -vvv
windows下需要运行(tp5手册:https://www.kancloud.cn/manual/thinkphp5/235128)
2: composer require workerman/workerman-for-win
第二步
tp 、fastadmin 框架 public 新建启动文件server.php
<?php
define('APP_PATH', __DIR__ . '/../application/');
define('BIND_MODULE','worker/Worker');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';
第三步
application下新建worker目录及worker.php文件
worker.php文件内容如下
<?php
namespace app\worker\controller;
use think\worker\Server;
use Workerman\Lib\Timer;
class Worker extends Server
{
protected $socket = 'websocket://0.0.0.0:2346';
protected $processes = 1;//进程数
protected $worker;
protected $HEARTBEAT_TIME = '60';//心跳时间,后端主动关闭客户端
public function __construct()
{
parent::__construct();
$this->worker->uidConnections = array(); //用户链接池 存储映射
}
/**
* 接收消息
* @param $connection
* @param $data
*/
public function onMessage($connection, $data)
{
//客户端与后端消息链接唯一标识
$uid = $connection->uid;
if($uid) {
$data=json_decode($data,true);
$message=['code'=>0,'msg'=>'你还活着','type'=>0,'data'=>[]];
if(!$data){
return true;
}
//区分各种业务处理
$method = $data['method'];
$is_push=0;//是否主动推送消息
switch ($method) {
//创建聊天室
case 'add_chat':
$is_push=1;//开启推送
$chat_id=1111;//你的聊天室id 返回给前端
$message=['code'=>0,'msg'=>'创建成功','type'=>-1,'data'=>$chat_id];
break;
//发送消息
case 'send':
$is_push=1;//开启推送
$message='你处理的消息信息';
//如果对方在线 向对方发送一条消息
$this->sendMessageByUid($data['user_id'],$message);
$message2=‘聊天消息列表';
//对方在线 更新对方消息接收列表(没做分页处理,分页后台发送单条信息前端使用push)
$this->sendMessageByUid($data['user_id'],$message2);
break;
//客户端主动来取消息列表
case 'list':
$is_push=1;//开启推送
$message=‘聊天消息列表';
break;
//客户端主动取聊天室内容
case 'chat_list':
$is_push=1;//开启推送
$post=[
'user_id'=>$uid,
'chat_id'=>$data['chat_id'],//聊天室id
'page'=>$data['page'],//分页数
];
$message=ChatList::getList($post);
break;
}
//向自己推送消息
if($is_push){
$this->sendMessageByUid($uid,$message);
}
}else{//查询不到用户信息,关闭此连接
$this->onClose($connection);
}
}
// 向所有验证的用户推送数据
function broadcast($message)
{
foreach($this->worker->uidConnections as $connection)
{
$connection->send($message);
}
}
// 针对uid推送数据
function sendMessageByUid($uid, $message)
{
if(isset($this->worker->uidConnections[$uid]))
{
$connection = $this->worker->uidConnections[$uid];
$connection->send(json_encode($message,true));
}
}
/**
* 当连接建立时触发的回调函数
* @param $connection
*/
public function onConnect($connection)
{
$connection->onWebSocketConnect = function($connection , $http_header)
{
// 可以在这里判断连接来源是否合法,不合法就关掉连接
// $_SERVER['HTTP_ORIGIN']标识来自哪个站点的页面发起的websocket连接
$arr_request=[
'域名1',
'域名2',
];
//判断是否合法连接
if(in_array( http_header['Host'],$arr_request) !=true)
{
$connection->close();
}
// 存客户端与websocket的映射,唯一连接标识(!!!关键)
if(!isset($connection->uid))
{
$connection->uid = $_SERVER['HTTP_TOKEN'];
$this->worker->uidConnections[$connection->uid]=$connection;
return;
}
};
}
/**
* 当连接断开时触发的回调函数
* @param $connection
*/
public function onClose($connection)
{
// //代表用户下线,清除用户信息
if(isset($connection->uid))
{
// 连接断开时删除映射
unset($this->worker->uidConnections[$connection->uid]);
}
}
/**
* 当客户端的连接上发生错误时触发
* @param $connection
* @param $code
* @param $msg
*/
public function onError($connection, $code, $msg)
{
echo "error $code $msg\n";
}
/**
* 每个进程启动
* @param $worker
*/
public function onWorkerStart($worker)
{
//每10秒检查一下客户端是否还连着服务端。超时未相应也会主动关闭与客户端的连接
Timer::add(10, 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.'秒';
$message=['code'=>0,'msg'=>$msg,'type'=>0,'data'=>[]];
$connection->send(json_encode($message,true));
// 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接
if ($time_now - $connection->lastMessageTime > $this->HEARTBEAT_TIME) {
$connection->close();
}
}
});
}
}
cmd 项目中到public目录下运行php server.php start -测试环境 生产环境 后面加-d
第三步 浏览器:
浏览器打开项目运行 console
ws = new WebSocket(“ws://127.0.0.1:3344”);
ws.onopen = function() {undefined
alert(“连接成功”);
ws.send(‘tom’);
alert(“给服务端发送一个字符串:tom”);
};
ws.onmessage = function(e) {undefined
alert(“收到服务端的消息:” + e.data);
};
ƒ (e) {undefined
alert(“收到服务端的消息:” + e.data);
}
更多推荐




所有评论(0)