swoole 极简聊天室
原本我是准备接着写我那个多进程教程的,今天心血来潮想看看swoole的websocket, 我就点开了这个 WebSocket 我看了看官网的demo,觉得看起来很简单嘛,
<?php
//官网demo
$server = new swoole_websocket_server("0.0.0.0", 9501);
$server->on('open', function (swoole_websocket_server $server, $request) {
echo "server: handshake success with fd{$request->fd}\n";//$request->fd 是客户端id
});
$server->on('message', function (swoole_websocket_server $server, $frame) {
echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
$server->push($frame->fd, "this is server");//$frame->fd 是客户端id,$frame->data是客户端发送的数据
//服务端向客户端发送数据是用 $server->push( '客户端id' , '内容')
});
$server->on('close', function ($ser, $fd) {
echo "client {$fd} closed\n";
});
$server->start();
我就是喜欢这种简单易懂的demo ,每行代码意思一看就明白
服务端有了,我找点客户端的js代码 火狐的MDN
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="UTF-8">
<script type="text/javascript">
var exampleSocket = new WebSocket("ws://0.0.0.0:9501");
exampleSocket.onopen = function (event) {
exampleSocket.send("亲爱的服务器!我连上你啦!");
};
exampleSocket.onmessage = function (event) {
console.log(event.data);
}
</script>
</head>
<body>
<input type="text" id="content">
<button onclick="exampleSocket.send( document.getElementById('content').value )">发送</button>
</body>
</html>
最后命令行运行php文件,之后浏览器打开html文件, F12打开调试界面看console,ok , 没有问题
这个时候我突然想到一个事情,因为我做多进程的那个教程里,在主进程中会将所有的子进程的句柄存起来,以后进行进程间通讯用。 那么 我将所有的客户端的链接存起来存成数组,每当一个客户端发送消息时,我就遍历这个客户端数组,将消息群发一遍,不久实现了聊天室了吗? 然后就,服务端代码成了这个样子
<?php
$map = array();//客户端集合
$server = new swoole_websocket_server("0.0.0.0", 9501);
$server->on('open', function (swoole_websocket_server $server, $request) {
global $map;//客户端集合
$map[$request->fd] = $request->fd;//首次连上时存起来
});
$server->on('message', function (swoole_websocket_server $server, $frame) {
global $map;//客户端集合
$data = $frame->data;
foreach($map as $fd){
$server->push($fd , $data);//循环广播
}
});
$server->on('close', function ($ser, $fd) {
echo "client {$fd} closed\n";
});
$server->start();
哈哈 , 我觉得这样就大功告成了,结果发现自己是 图样图森破 大家可以自己试试,运行php后 , 浏览器打开两个页面,看看console.log的内容是什么
运行良好,可是并没有实现我们说的那种聊天效果。 找找原因吧。 我第一反映看看$map里面是什么,就输出看看,结果发现这个map里面只有一个元素。 唉,不对啊,我这是全局变量,难道不应该是有几个客户端链接,就有几个元素吗? 这是怎么回事啊,竟然没有保存到所有客户端id?
到了这一步,我解决不了map变量的这个问题了,然后我就想看看那个fd是什么东西, 老规矩 var_dump输出 , 发现fd就是 int类型的数字,并且是自增的 这好办了,不就是数字嘛
于是呼,我就这样做 变量存不了,我搞不定,我存文本里嘛。 最终版 websocket.php
<?php
$server = new swoole_websocket_server("0.0.0.0", 9501);
$server->on('open', function (swoole_websocket_server $server, $request) {
file_put_contents( __DIR__ .'/log.txt' , $request->fd);
});
$server->on('message', function (swoole_websocket_server $server, $frame) {
global $client;
$data = $frame->data;
$m = file_get_contents( __DIR__ .'/log.txt');
for ($i=1 ; $i<= $m ; $i++) {
echo PHP_EOL . ' i is ' . $i . ' data is '.$data . ' m = ' . $m;
$server->push($i, $data );
}
/*一直轮询
while(1){
echo '啊啊'.mt_rand(0,9999);
$serv->push($task_id, '用户'.mt_rand(0,9999));
//模拟慢速任务
sleep(5);
}
*/
});
$server->on('WorkerStart', function (swoole_websocket_server $server, $worker_id){
//每三秒发送后断开
Swoole\Timer::tick(3000, function (int $timer_id, $server) {
echo "timer_id #$timer_id, after 3000ms.\n";
$server->connections=[1,2,3,4,5];
foreach ($server->connections as $fd){
$rand = mt_rand(0,9999);
$server->push($fd, $rand);
$server->close($fd);//断开链接
}
}, $server);
});
$server->on('close', function ($ser, $fd) {
echo "client {$fd} closed\n";
});
$server->start();
再次打开html文件,多个页面进行输入观察,ok,可以了。
当然,作为聊天室,我这写的也过于简陋了,界面大家自己可以写的好看一些(因为我懒的写界面) 还有,每次的发送聊天的记录,应该存起来,这样,如果有新的连接连过来的时候,先把以前的聊天记录发过去,这样,我想体验更好一些
然后,大家可以愉快的聊天了。哈哈
猜你喜欢
Laravel验证码
阅读 620Composer生成Laravel验证码
LaravelS基于Swoole实现高性能 HTTP 服务器
阅读 1630LaravelS基于Swoole 配置nginx等
PHP定时任务
阅读 1597PHP框架Laravel定时任务的实现
Swoole 扩展安装与使用入门
阅读 1774Swoole从入门到实战
抖音接入
阅读 1957PHP 接入抖音开放平台
Git使用
阅读 592Git基本配置/服务器搭建仓库
在 Laravel 中集成 Swoole 实现 WebSocket 服务器
阅读 2286基于 LaravelS 扩展包把 Swoole 集成到 Laravel 项目来实现 WebSocket 服务器,以便与客户端进行 WebSocket 通信从而实现广播功能。
黑客、后门
阅读 1425留下的网站后门,可以作什么?