前提:
- linux环境下PHP有可用的Swoole扩展。
- 9501端口可访问。
后端
<?php
class Helper {
/**
* @function 将数组中的null值转化为空字符串
* @param $arr array 要转化的数组
* @return array
* @other void
*/
public static function nullToEmptyString($arr) {
if (! $arr) {
return $arr;
}
foreach ($arr as $key => $value) {
if (null === $value) {
$arr[$key] = '';
}
if (is_array($value)) {
$arr[$key] = static::nullToEmptyString($value);
}
}
return $arr;
}
/**
* @function 统一的RestFul风格的Api格式
* @param $code int 状态码
* @param $msg string 显示的信息
* @param $data mixed 返回的数据
* @return string
* @other void
*/
public static function jsonReturn($code = 0, $msg = '', $data = []) {
header('Content-type:text/json;Charset=UTF-8');
return json_encode([
'code' => $code,
'msg' => $msg,
'data' => $data === null ? [] : static::nullToEmptyString($data),
], JSON_UNESCAPED_UNICODE);
}
/**@function 配置人数
* @param $num
* @return bool
*/
public static function setPersonNumber($num) {
return file_put_contents(__DIR__ . '/personNum.txt', $num);
}
/**
* @function 获取人数
* @return int
*/
public static function getPersonNumber() {
$file = __DIR__ . '/personNum.txt';
if(! file_exists($file)) {
return 0;
}
return file_get_contents($file);
}
/**
* @function 发消息对外广播
* @param $ws object \Swoole\WebSocket\Server
* @param $msg string 广播数据
* @return null
*/
public static function broadcast(Swoole\WebSocket\Server $ws, $msg) {
$fd = static::getPersonNumber();
if($fd > 0) {
for($i = 1; $i <= $fd; $i++) {
$ws->push($i, $msg);
}
}
return null;
}
}
//创建WebSocket Server对象,监听0.0.0.0:9501端口。
$ws = new Swoole\WebSocket\Server('0.0.0.0', 9501);
//监听WebSocket连接打开事件。
$ws->on('Open', function ($ws, $request) {
$ws->nickname = '游客'. $request->fd;
Helper::setPersonNumber($request->fd);
Helper::broadcast($ws, Helper::jsonReturn(0, '', ['type' => 'enter', 'user' => $ws->nickname, 'content' => '']));
return null;
});
//监听WebSocket消息事件。
$ws->on('Message', function ($ws, $frame) {
Helper::broadcast($ws, Helper::jsonReturn(0, '', ['type' => 'say', 'user' => $ws->nickname, 'content' => htmlspecialchars($frame->data)]));
return null;
});
//监听WebSocket连接关闭事件。
$ws->on('Close', function ($ws, $fd) {
Helper::setPersonNumber(-- $fd);
Helper::broadcast($ws, Helper::jsonReturn(0, '', ['type' => 'leave', 'user' => $ws->nickname, 'content' => '']));
return null;
});
$ws->start();
前端
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>简易聊天室</title>
<style>
body * {font-size: 20px;width: 400px;height: 40px;}
</style>
</head>
<body>
<input type="text" id="text">
<input type="button" id="send" value="发送">
<div id="box"></div>
</body>
<script>
//初始化
var websocket = new WebSocket('ws://192.168.3.180:9501/swoole.php');
//打开事件
websocket.onopen = function (evt) {
document.getElementById('send').onclick = function() {
var msg = document.getElementById('text').value;
if(msg) {
websocket.send(msg);
}
}
};
//消息事件
websocket.onmessage = function (evt) {
var data = JSON.parse(evt.data);
var data = data.data;
if(data.type == 'enter') {
var e = '<p style="color:green">' + data.user + '进入聊天室</p>';
} else if(data.type == 'leave') {
var e = '<p style="color:red">' + data.user + '离开聊天室</p>';
} else if (data.type == 'say') {
var e = '<p style="color:black">' + data.user + '说:' + data.content + '</p>';
}
var element = document.getElementById('box').innerHTML += e;
};
//关闭事件
websocket.onclose = function (evt) {
console.log("WebSocket 已断开连接");
};
//错误事件
websocket.onerror = function (evt, e) {
console.log("WebSocket 错误:" + evt.data);
};
</script>
</html>