php+websocket+layIm实现即时通讯、单聊、群聊、分组等功能
·

如有疑问,欢迎打扰~~~~~
php + websocket 实现即时通讯。

右键菜单功能。

群聊功能以及右键菜单功能
<?php
namespace app\server\controller;
use think\worker\Server;
use think\Session;
use Workerman\Lib\Timer;
// 心跳间隔55秒
define('HEARTBEAT_TIME', 55);
define('CHECK_HEARTBEAT_TIME', 10); // 检查连接的间隔时间
class Worker extends Server
{
protected $socket = 'websocket://www.tp5.com:2346';
protected $processes = 1;
protected $uidConnections = array();
static $count = 0;
/**
* 收到信息
* @param $connection
* @param $data
*/
public function onMessage($connection, $data)
{
// 判断当前客户端是否已经验证,既是否设置了uid,设置了直接发送消息,未设置第一次为设置uid
dump('开始');
$connection->lastMessageTime = time();
if(!isset($connection->uid))
{
$uid = json_decode($data,true);
if ($uid['message_type'] == 'event'){
dump($uid);
switch ($uid['type']){
case 'sendOrder':
$arr = [
'message_type' => 'event',
'type' => 'sendOrder',
'username' => $uid['username'],
'imgUrl' => $uid['imgUrl'],
'info' => $uid['info'],
];
$receipt = json_encode($arr,JSON_UNESCAPED_UNICODE );
break;
case 'online':
$arr = [
'message_type' => 'event',
'type' => 'online',
'username' => $uid['username'],
];
$receipt = json_encode($arr,JSON_UNESCAPED_UNICODE );
break;
}
$this->sendUser($receipt);
}else {
$managerInfo = $this->getManagerInfo($uid['id'], $uid);
dump($managerInfo);
if (!empty($managerInfo) && !empty($uid['userType'])){
db('wx_wechat_info')->where("openId = '{$uid['id']}'")->update(array('onlineTime'=>time(),'onlineStatus'=>'online'));
}
if (!empty($managerInfo) && empty($uid['userType'])){
db('sw_manager')->where("mg_id = {$uid['id']}")->update(array('online_time'=>time(),'online_status'=>'online'));
}
// 没验证的话把第一个包当做uid(这里为了方便演示,没做真正的验证)
$connection->uid = $uid['id'];
/* 保存uid到connection的映射,这样可以方便的通过uid查找connection,
* 实现针对特定uid推送数据
*/
$this->uidConnections[$connection->uid] = $connection;
//---------------连接时候更新状态-----------------
$receipt = '';
switch ($uid['message_type']){
case 'init':
$arr = [
'message_type' => 'init',
'id' => $uid['id'],
'username' => $uid['username'],
'online_status' => 'online',
'remark' => !empty($managerInfo['remark']) ? $managerInfo['remark'] : '',
];
$receipt = json_encode($arr,JSON_UNESCAPED_UNICODE );
break;
}
$this->sendUser($receipt);
return;
}
}else{
$data = json_decode($data,true);
dump($data);
if (!empty($data['type'])){
switch ($data['type']){
case 'chatMessage':
$chatType = $data['data']['to']['type'];
$arr = [
'message_type'=> 'chatMessage',
'data'=>[
'username' => $data['data']['mine']['username'],
'avatar' => $data['data']['mine']['avatar'],
'id' => $chatType === 'friend' ? $data['data']['mine']['id'] : $data['data']['to']['id'],
'type' => $chatType,
'content' => $data['data']['mine']['content'],
'formid' => $data['data']['mine']['id'],
'timestamp' => time()*1000,
]
];
if ($chatType === 'friend'){
$name = $data['data']['to']['username'];
$form = 'msg_message';
$receipt = json_encode($arr,JSON_UNESCAPED_UNICODE );
$this->sendMessageByUid($data['data']['to']['id'],$receipt);
} else {
$name = $data['data']['to']['name'];
$form = 'msg_group_message';
$groupId = $data['data']['to']['id'];
$groupArr = db('msg_group_relation')->where("msGId IN ('{$groupId}') AND mgId <> {$data['data']['mine']['id']}")->field('msGId,mgId')->select();
$receipt = json_encode($arr,JSON_UNESCAPED_UNICODE );
foreach ($groupArr as $value){
$this->sendMessageByUid($value['mgId'],$receipt);
}
}
$keyword = $data['data']['mine']['content'];
$content = $this->getNeedBetween($keyword, '[' , ']' );
$type = substr($keyword,0,strpos($keyword, '['));
//发送方数据
$sendMessage = [
'status' => $data['status'] === 'online' ? 2 : 1,
'content' => is_string($content) ? $content : $data['data']['mine']['content'],
'type' => $type,
'fromUserName' => $data['data']['mine']['username'],
'fromUserId' => $data['data']['mine']['id'],
'toUserName' => $name,
'toUserId' => $data['data']['to']['id'],
'addTime' => date('Y-m-d H:i:s', time())
];
db($form)->insert($sendMessage);
break;
case 'onClose':
$arr = [
'message_type'=> 'chatMessage',
'data'=>[
'system' => 'true',
'id' => $data['data']['mine']['id'],
'type' => 'friend',
'content' => '对方已离线',
]
];
$receipt = json_encode($arr,JSON_UNESCAPED_UNICODE );
$this->sendMessageByUid($data['data']['to']['id'],$receipt);
break;
default:
$this->sendUser('1111111');
}
}
}
}
function getNeedBetween($kw1,$mark1,$mark2){
$kw=$kw1;
$kw='123'.$kw.'123';
$st =stripos($kw,$mark1);
$ed =stripos($kw,$mark2);
if(($st==false||$ed==false)||$st>=$ed)
return 0;
$kw=substr($kw,($st+1),($ed-$st-1));
return $kw;
}
//查找当前客户信息
public function getManagerInfo($id, $info)
{
if (!empty($info['userType'])){
$managerInfo = db('wx_wechat_info')->alias('a')->join('wx_group_customer b', 'a.id = b.wxId')->where("openId = '{$id}'")->field('a.*,b.remark')->find();
}else {
$managerInfo = db('sw_manager')->where("mg_id = {$id}")->find();
}
return $managerInfo;
}
/**
* 当连接建立时触发的回调函数
* @param $connection
*/
public function onConnect($connection)
{
self::$count++;
}
/**
* 当连接断开时触发的回调函数
* @param $connection
*/
public function onClose($connection)
{
dump('关闭连接时触发的');
self::$count--;
if(isset($connection->uid))
{
//---------连接断开时删除映射并传给客户端----
$data = $connection->uid;
$arr = [
'message_type' => 'updateInit',
'id' => $data,
'online_status' => 'offline',
];
$updateArr = [
'message_type'=> 'chatMessage',
'data'=>[
'system' => 'true',
'id' => $data,
'type' => 'friend',
'content' => '对方已离线',
]
];
$receipt = json_encode($arr,JSON_UNESCAPED_UNICODE );
$receiptArr = json_encode($updateArr,JSON_UNESCAPED_UNICODE );
$this->sendUser($receipt);
$this->sendUser($receiptArr);
unset($this->uidConnections[$connection->uid]);
//---------修改数据库状态----
if (!empty($data) && is_numeric($data)){
db('sw_manager')->where("mg_id = {$data}")->update(array('offline_time'=>time(),'online_status'=>'offline'));
}
if (!empty($data) && !is_numeric($data)){
db('wx_wechat_info')->where("openId = '{$data}'")->update(array('onlineTime'=>time(),'onlineStatus'=>'offline'));
}
}
}
/**
* 当客户端的连接上发生错误时触发
* @param $connection
* @param $code
* @param $msg
*/
public function onError($connection, $code, $msg)
{
echo "error $code $msg\n";
}
/**
* 每个进程启动
* @param $worker
*/
public function onWorkerStart($worker)
{
dump('--------------启动进程------------------');
Timer::add(CHECK_HEARTBEAT_TIME, function()use($worker){
$time_now = time();
foreach($worker->connections as $connection) {
// 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间
if (empty($connection->lastMessageTime)) {
$connection->lastMessageTime = $time_now;
continue;
}
// 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接
if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) {
$connection->close();
}
}
});
}
// 向所有验证的用户推送数据
function sendUser($message)
{
foreach($this->uidConnections as $connection)
{
$connection->send($message);
}
}
// 针对uid推送数据
function sendMessageByUid($uid, $message)
{
if(isset($this->uidConnections[$uid]))
{
$connection = $this->uidConnections[$uid];
$connection->send($message);
return true;
}
return false;
}
}
更多推荐
所有评论(0)