一、程序目录结构

二、代码展示

附LayIM开发文档:https://www.layui.com/doc/modules/layim.html

1、前端代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>websocket连接</title>
<link rel="stylesheet" href="./layui/css/layui.css" media="all">
<script src="./layui/jquery.min.js"></script>
<script src="./layui/layui.js"></script>
</head>
<body style="background: url(./layui/images/irongrip.png) repeat"> </body>
<script>
layui.use('layim', function(layim){
//基础配置
layim.config({
//获取主面板列表信息
init: {
url: "./getUserList.php?id=<?php echo $_GET['id']?>" //接口地址(返回的数据格式见下文)
,type: 'get' //默认get,一般可不填
,data: {} //额外参数
}
//获取群员接口
,members: {
url: "./getMembers.php" //接口地址(返回的数据格式见下文)
,type: 'get' //默认get,一般可不填
,data: {} //额外参数
},
uploadFile: {
url: ""
}
,uploadImage: {
url: ""
}
,brief: false //是否简约模式(默认false,如果只用到在线客服,且不想显示主面板,可以设置 true)
,title: '我的LayIM' //主面板最小化后显示的名称
,maxLength: //最长发送的字符长度,默认3000
,isfriend: true //是否开启好友(默认true,即开启)
,isgroup: true //是否开启群组(默认true,即开启)
,right: '0px' //默认0px,用于设定主面板右偏移量。该参数可避免遮盖你页面右下角已经的bar。
,chatLog: "" //聊天记录地址(如果未填则不显示)
,find: "" //查找好友/群的地址(如果未填则不显示)
,copyright: false //是否授权,如果通过官网捐赠获得LayIM,此处可填true
}); var socket = new WebSocket("ws://127.0.0.1:7272");
socket.onopen = function(){
<?php $id = $_GET['id'];
$conn = @mysql_connect("127.0.0.1", "root", "root") or die("连接数据库失败");
mysql_select_db("layim");
$rows = mysql_query("select * from snake_chatuser where id = $id");
$info = array();
while ($row = mysql_fetch_array($rows)) {
$info = $row;
}
?>
var id = '<?php echo $info['id'];?>';
var username = '<?php echo $info['username'];?>';
var avatar = '<?php echo $info['avatar'];?>';
var sign = '<?php echo $info['sign'];?>';
//登录
var login_data = '{"type":"init","id":"'+id+'","username":"'+username+'","avatar":"'+avatar+'","sign":"'+sign+'"}';
socket.send( login_data );
console.log("websocket握手成功!");
}; //监听收到的消息
socket.onmessage = function(res){
// console.log(res);
var data = eval("("+res.data+")");
switch(data['message_type']){
// 服务端ping客户端
case 'ping':
socket.send('{"type":"ping"}');
break;
// 登录 更新用户列表
case 'init':
//console.log(data['id']+"登录成功");
//layim.getMessage(res.data); //res.data即你发送消息传递的数据(阅读:监听发送的消息)
break;
//添加 用户
case 'addUser':
//console.log(data.data);
layim.addList(data.data);
break;
//删除 用户
case 'delUser':
layim.removeList({
type: 'friend'
,id: data.data.id //好友或者群组ID
});
break;
// 添加 分组信息
case 'addGroup':
// console.log(data.data);
layim.addList(data.data);
break;
case 'delGroup':
layim.removeList({
type: 'group'
,id: data.data.id //好友或者群组ID
});
break;
// 检测聊天数据
case 'chatMessage':
//console.log(data.data);
layim.getMessage(data.data);
break;
// 离线消息推送
case 'logMessage':
console.log();
setTimeout(function(){layim.getMessage(data.data)}, );
break;
// 用户退出 更新用户列表
case 'logout':
break;
//聊天还有不在线
case 'ctUserOutline':
console.log('');
//layer.msg('好友不在线', {'time' : 1000});
break; }
}; //layim建立就绪
layim.on('ready', function(res){ layim.on('sendMessage', function(res){
console.log(res);
// 发送消息
var mine = JSON.stringify(res.mine);
var to = JSON.stringify(res.to);
var login_data = '{"type":"chatMessage","data":{"mine":'+mine+', "to":'+to+'}}';
socket.send( login_data ); });
});
}); </script>
</html>

2、后台核心代码

<?php
use \GatewayWorker\Lib\Gateway;
use \GatewayWorker\Lib\Db;
/**
* 主逻辑
* 主要是处理 onConnect onMessage onClose 三个方法
* onConnect 和 onClose 如果不需要可以不用实现并删除
*/
class Events
{
public static function onConnect($client_id) { }
/**
* 当客户端发来消息时触发
* @param int $client_id 连接id
* @param mixed $message 具体消息
*/
public static function onMessage($client_id, $data) {
$message = json_decode($data, true);
$message_type = $message['type'];
switch($message_type) {
case 'init':
// uid
$uid = $message['id'];
// 设置session
$_SESSION = [
'username' => $message['username'],
'avatar' => $message['avatar'],
'id' => $uid,
'sign' => $message['sign']
]; // 将当前链接与uid绑定
Gateway::bindUid($client_id, $uid);
// 通知当前客户端初始化
$init_message = array(
'message_type' => 'init',
'id' => $uid,
);
Gateway::sendToClient($client_id, json_encode($init_message)); //查询最近1周有无需要推送的离线信息
$db1 = Db::instance('db1'); //数据库链接
$time = time() - 7 * 3600 * 24;
$resMsg = $db1->select('id,fromid,fromname,fromavatar,timeline,content')->from('snake_chatlog')
->where("toid= {$uid} and timeline > {$time} and type = 'friend' and needsend = 1" )
->query();
//var_export($resMsg);
if( !empty( $resMsg ) ){ foreach( $resMsg as $key=>$vo ){ $log_message = [
'message_type' => 'logMessage',
'data' => [
'username' => $vo['fromname'],
'avatar' => $vo['fromavatar'],
'id' => $vo['fromid'],
'type' => 'friend',
'content' => htmlspecialchars( $vo['content'] ),
'timestamp'=> $vo['timeline'] * 1000,
]
]; Gateway::sendToUid( $uid, json_encode($log_message) ); //设置推送状态为已经推送
$db1->query("UPDATE `snake_chatlog` SET `needsend` = '0' WHERE id=" . $vo['id']); }
} //查询当前的用户是在哪个分组中,将当前的链接加入该分组
$ret = $db1->query("select `groupid` from `snake_groupdetail` where `userid` = {$uid} group by `groupid`");
if( !empty( $ret ) ){
foreach( $ret as $key=>$vo ){
Gateway::joinGroup($client_id, $vo['groupid']); //将登录用户加入群组
}
}
unset( $ret );
return;
break;
case 'addUser' :
//添加用户
$add_message = [
'message_type' => 'addUser',
'data' => [
'type' => 'friend',
'avatar' => $message['data']['avatar'],
'username' => $message['data']['username'],
'groupid' => $message['data']['groupid'],
'id' => $message['data']['id'],
'sign' => $message['data']['sign']
]
];
Gateway::sendToAll( json_encode($add_message), null, $client_id );
return;
break;
case 'delUser' :
//删除用户
$del_message = [
'message_type' => 'delUser',
'data' => [
'type' => 'friend',
'id' => $message['data']['id']
]
];
Gateway::sendToAll( json_encode($del_message), null, $client_id );
return;
break;
case 'addGroup':
//添加群组
$uids = explode( ',', $message['data']['uids'] );
$client_id_array = [];
foreach( $uids as $vo ){
$ret = Gateway::getClientIdByUid( $vo ); //当前组中在线的client_id
if( !empty( $ret ) ){
$client_id_array[] = $ret['0']; Gateway::joinGroup($ret['0'], $message['data']['id']); //将这些用户加入群组
}
}
unset( $ret, $uids ); $add_message = [
'message_type' => 'addGroup',
'data' => [
'type' => 'group',
'avatar' => $message['data']['avatar'],
'id' => $message['data']['id'],
'groupname' => $message['data']['groupname']
]
];
Gateway::sendToAll( json_encode($add_message), $client_id_array, $client_id );
return;
break;
case 'joinGroup':
//加入群组
$uid = $message['data']['uid'];
$ret = Gateway::getClientIdByUid( $uid ); //若在线实时推送
if( !empty( $ret ) ){
Gateway::joinGroup($ret['0'], $message['data']['id']); //将该用户加入群组 $add_message = [
'message_type' => 'addGroup',
'data' => [
'type' => 'group',
'avatar' => $message['data']['avatar'],
'id' => $message['data']['id'],
'groupname' => $message['data']['groupname']
]
];
Gateway::sendToAll( json_encode($add_message), [$ret['0']], $client_id ); //推送群组信息
} return;
break;
case 'addMember':
//添加群组成员
$uids = explode( ',', $message['data']['uid'] );
$client_id_array = [];
foreach( $uids as $vo ){
$ret = Gateway::getClientIdByUid( $vo ); //当前组中在线的client_id
if( !empty( $ret ) ){
$client_id_array[] = $ret['0']; Gateway::joinGroup($ret['0'], $message['data']['id']); //将这些用户加入群组
}
}
unset( $ret, $uids ); $add_message = [
'message_type' => 'addGroup',
'data' => [
'type' => 'group',
'avatar' => $message['data']['avatar'],
'id' => $message['data']['id'],
'groupname' => $message['data']['groupname']
]
];
Gateway::sendToAll( json_encode($add_message), $client_id_array, $client_id ); //推送群组信息
return;
break;
case 'removeMember':
//将移除群组的成员的群信息移除,并从讨论组移除
$ret = Gateway::getClientIdByUid( $message['data']['uid'] );
if( !empty( $ret ) ){ Gateway::leaveGroup($ret['0'], $message['data']['id']); $del_message = [
'message_type' => 'delGroup',
'data' => [
'type' => 'group',
'id' => $message['data']['id']
]
];
Gateway::sendToAll( json_encode($del_message), [$ret['0']], $client_id );
} return;
break;
case 'delGroup':
//删除群组
$del_message = [
'message_type' => 'delGroup',
'data' => [
'type' => 'group',
'id' => $message['data']['id']
]
];
Gateway::sendToAll( json_encode($del_message), null, $client_id );
return;
break;
case 'chatMessage':
$db1 = Db::instance('db1'); //数据库链接
// 聊天消息
$type = $message['data']['to']['type'];
$to_id = $message['data']['to']['id'];
$uid = $message['data']['mine']['id']; $chat_message = [
'message_type' => 'chatMessage',
'data' => [
'username' => $message['data']['mine']['username'],
'avatar' => $message['data']['mine']['avatar'],
'id' => $type === 'friend' ? $uid : $to_id,
'type' => $type,
'content' => htmlspecialchars($message['data']['mine']['content']),
'timestamp'=> time()*1000,
]
];
//聊天记录数组
$param = [
'fromid' => $uid,
'toid' => $to_id,
'fromname' => $message['data']['mine']['username'],
'fromavatar' => $message['data']['mine']['avatar'],
'content' => htmlspecialchars($message['data']['mine']['content']),
'timeline' => time(),
'needsend' => 0
];
switch ($type) {
// 私聊
case 'friend':
// 插入
$param['type'] = 'friend';
if( empty( Gateway::getClientIdByUid( $to_id ) ) ){
$param['needsend'] = 1; //用户不在线,标记此消息推送
}
$db1->insert('snake_chatlog')->cols( $param )->query();
return Gateway::sendToUid($to_id, json_encode($chat_message));
// 群聊
case 'group':
$param['type'] = 'group';
$db1->insert('snake_chatlog')->cols( $param )->query();
return Gateway::sendToGroup($to_id, json_encode($chat_message), $client_id);
}
return;
break;
case 'hide':
case 'online':
$status_message = [
'message_type' => $message_type,
'id' => $_SESSION['id'],
];
$_SESSION['online'] = $message_type;
Gateway::sendToAll(json_encode($status_message));
return;
break;
case 'ping':
return;
default:
echo "unknown message $data" . PHP_EOL;
}
} /**
* 当用户断开连接时触发
* @param int $client_id 连接id
*/
public static function onClose($client_id) {
$logout_message = [
'message_type' => 'logout',
'id' => $_SESSION['id']
];
Gateway::sendToAll(json_encode($logout_message));
}
}

三、页面效果图

有需要了解的加QQ:2575404985,可以兼容linux与windows

在linux下运行方式,在workerman目录下创建start.sh,代码如下:

#!/bin/bash
php ./Applications/start_register.php start &
php ./Applications/start_gateway.php start &
php ./Applications/start_businessworker.php start &

四、案例

最新文章

  1. word20161222
  2. 【jQuery api】isFunction()
  3. HBase与MongDB等NoSQL数据库对照
  4. MyEclipse------File类的各种方法
  5. 【POJ】3261 Milk Patterns
  6. uva 10065 (凸包+求面积)
  7. linux下cat命令详解
  8. PDB符号文件信息
  9. apache 服务器端口被IIS服务器占用
  10. RAC 11.2.0.4 安装 遇到 INS-06001
  11. EOS智能合约开发(二):EOS创建和管理钱包
  12. 深度学习Bible学习笔记:第七章 深度学习中的正则化
  13. AangularJS过滤器详解
  14. NO.3_1:自学python之路------番外:第三方库安装、numpy
  15. 第一个spring冲刺总结
  16. EL函数库
  17. Luckily general gradient for spherical harmonics is defined
  18. MySQL-5.7 创建及查看触发器
  19. DCGAN、WGAN、WGAN-GP、LSGAN、BEGAN原理总结及对比
  20. 《the art of software testing》第四章 测试用例的设计

热门文章

  1. react-浏览后的想法
  2. canvas裁剪之后的base64转换为上传文件blob对象
  3. ASPNET Razor 使用 @Ajax.BeginForm 需要注意到的细节
  4. C/C++异常处理机制
  5. 重学数据结构系列之——平衡树之SB Tree(Size Blanced Tree)
  6. xcode 4.5 new feature __ ios6 新特性
  7. spring装配集合
  8. ios逆向工程
  9. 破解IntelliJ IDEA 2017
  10. ubuntu拨号上网以及路由设置