PHP代码块
注意需要下载 workman 快捷安装 composer require workerman/workerman
在这里插入代码片<?php
use Workerman\Worker;
//自动加载
require __DIR__ . '/../vendor/autoload.php';
//创建一个Worker监听127.0.0.1:8000, 使用websocket协议通讯
$ws_worker = new Worker("websocket://本地连接");
//启动4个进程对外提供服务
$ws_worker->count = 4;
//服务启动的时候
$ws_worker->onWorkerStart = function (Worker $task){
//初始化工作
//utf8 gbk
echo '服务启动';
};
//用户连接时
$ws_worker->onConnect = function (Workerman\Connection\TcpConnection $connection)use($ws_worker){
//初始化用户信息
};
//当接收到客户端发来的数据后显示数据并回发到客户端
$ws_worker->onMessage = function($connection, $data) use($ws_worker){
//记录日志
addLog('-----------------------'.$connection->id.'-----------------------------');
addLog('发送的原始信息'.$data);
//解析数据
$data = json_decode($data,true);
if( !is_array($data) || !isset($data['type'])){
$connection->send(json_encode(['type'=>'err','msg'=>"数据格式错误"]));
return;
}
//记录转换之后的数据
addLog("转换之后的数据\n".var_export($data,true) );
switch ( $data['type'] ){
case 'login':
//登录操作
//判断是否重名
$nick = $data['nick'];
foreach ($ws_worker->connections as $con) {
if( isset($con->nick) && $con->nick == $nick ){
$connection->send(json_encode([
'type'=>'err',
'msg'=>'该昵称已登录',
]));
return false;
}
}
$connection->nick =$nick;
$connection->send(json_encode([
'type'=>$data['type'],
'code'=>1,
'nick'=>$nick
]));
//通知所有人
getNickList($ws_worker);
break;
case 'getOnline':
//获取所有在线人数
//只发送自己
getNickList($ws_worker,$connection);
break;
case 'sendMsg':
$sendData = [
'type' => $data['type'],
'data'=>[
'type'=>$data['data']['type'],
'time'=>date('Y-m-d H:i:s'),
'formNick'=>$connection->nick,
'toNick'=>$data['data']['toNick'],
'msg'=>$data['data']['msg'],
]
];
// 1 所有人 2 私聊 3 管理员
$type = $data['data']['type'];
foreach ($ws_worker->connections as $con) {
//所有人 和管理员
if( $type == 1 || $type == 3){
$con->send(json_encode($sendData));
continue;
}
//私聊
//排除没有登录的用户
if( !isset($con->nick) ){
continue;
}
//查找到需要聊天的用户
if( $data['data']['toNick'] == $con->nick ){
$con->send(json_encode($sendData));
//记录聊天记录
$connection->send(json_encode($sendData));
}
}
break;
}
};
//用户断开连接时
$ws_worker->onClose = function (Workerman\Connection\TcpConnection $con) use ( $ws_worker){
// //修改用户状态为离线
// echo $con->id .'断开连接';
// //向所有在线用户发送某某离线信息
// foreach ($ws_worker->connections as $connection ){
// $connection->send( $con->id .'断开连接');
// }
};
//服务重启
$ws_worker->onWorkerReload = function (){
};
//服务断开
$ws_worker->onWorkerStop = function (){
};
function addLog($data){
$path = date('Y/m/d');
if( !is_dir($path) ){
//可递归创建
mkdir($path,0777,true);
}
$log = '【'.date('Y-m-d H:i:s').'】:'.$data."\n";
file_put_contents($path.'/websocket.log',$log,FILE_APPEND);
}
//获取当前在线的昵称 并发送消息
function getNickList($ws_worker,$connection = null){
//获取所有在线人数
$nickList = [];
foreach ($ws_worker->connections as $con) {
if( isset($con->nick) ){
$nickList[] = $con->nick;
}
}
$sendData = [
'type'=>'getOnline',
'data'=>$nickList
];
if( $connection ){
$connection ->send(json_encode($sendData));
return ;
}
//给所有人发送消息
foreach ($ws_worker->connections as $con){
$con->send(json_encode($sendData));
}
}
//运行worker
$ws_worker->runAll();
前端代码块
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<noscript>
<iframe src=*.html></iframe>
</noscript>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body onselectstart="return false">
请输入昵称:<input type="text" id="nick">
<input type="submit" id="login" value="登录">
<br>
当前登录:<span style="color: red" id="selfNick">未登录</span>
<br>
在线用户(点击用户名发送私聊)
<div style="width: 500px;height: 100px;border: 1px solid red" id="onlineDiv"></div>
聊天框
<div style="width: 500px;height: 300px;border: 1px solid red" id="msgDiv"></div>
选中发送人:
<select id="userList">
</select>
<input type="text" id="sendMsg">
<input type="submit" id="send" value="发送">
<noscript>
<iframe src='*.htm'></iframe>
</noscript>
</body>
</html>
<script>
//在线用户列表
let onlineUser = [
'管理员',
'张三'
];
//信息列表
//type 1 公共 2 私聊 3 管理员
let msgList = [
// {
// type:3,
// time:'2021-01-01 12:00:00',
// formNick:'管理员',
// toNick:'',
// msg:'123132',
// },
// {
// type: 1,
// time:'2021-01-01 12:00:00',
// formNick:'管理员',
// toNick:'',
// msg:'123132',
// }
];
let isLogin = false;
let selfNick = '';
let ws = new WebSocket("ws://自己本地连接");
//当接收到信息的时候
ws.onmessage = function (res) {
//res.data 必须是个json 字符串
let data = JSON.parse(res.data)
switch (data.type) {
case 'login':
//登录
isLogin = true;
selfNick = data.nick;
$('#selfNick').html(data.nick);
alert('登录成功')
break;
case 'sendMsg':
//接收消息
msgList.push(data.data);
readMsg();
break;
case 'getOnline':
onlineUser = data.data
readOnlineUser();
break;
case 'err':
alert(data.msg);
}
console.log(res, data);
}
ws.onopen = function () {
//获取当前在线用户
ws.send(JSON.stringify({
type: 'getOnline'
}));
}
//登录
$('#login').click(function () {
let nick = $('#nick').val();
if (!nick) {
alert('昵称不能为空');
}
let data = {
type: 'login',
nick: nick
};
ws.send(JSON.stringify(data));
})
//点击私聊
$(document).on('click', '.sl', function () {
if (!isLogin) {
alert('请登录');
return;
}
$('#userList').val($(this).html());
})
//发送聊天
$('#send').click(function () {
if (!isLogin) {
alert('请先登录');
return;
}
//选中的聊天人
let sendUser = $('#userList').val() == '所有人' ? '' : $('#userList').val()
//判断聊天类型
let type = 1
if (sendUser) {
type = 2;
} else if (selfNick == '管理员') {
type = 3
}
let data = {
type: 'sendMsg',
data: {
type: type,
toNick: sendUser == '所有人' ? '' : sendUser,
msg: $('#sendMsg').val(),
},
};
ws.send(JSON.stringify(data));
})
//读取聊天数据
function readMsg() {
var html = '';
for (i in msgList) {
console.log(i);
if (msgList[i].type == 1) {
html += '<div>';
} else if (msgList[i].type == 2) {
html += '<div>【私聊】';
} else {
html += '<div style="color: red">';
}
html += msgList[i].formNick + '(' + msgList[i].time + '):' + msgList[i].msg + '</div><br>'
}
$('#msgDiv').html(html)
}
//读取在线用户信息
function readOnlineUser() {
let html = '';
let selectHtml = '<option>所有人</option>';
for (i in onlineUser) {
html += '<a href="#" class="sl">' + onlineUser[i] + '</a> '
selectHtml += '<option value="' + onlineUser[i] + '">' + onlineUser[i] + '</option>'
}
$('#onlineDiv').html(html)
$('#userList').html(selectHtml)
}
readMsg()
</script>