本来我是准备接着写我那个多进程教程的,今天心血来潮想看看swoole的websocket,
我就点开了这个
WebSocket
我看了看官网的demo,以为看起来很简单嘛,javascript
<?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 ,每行代码意思一看就明白php
服务端有了,我找点客户端的js代码
火狐的MDNhtml
<!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 , 没有问题java
这个时候我忽然想到一个事情,由于我作多进程的那个教程里,在主进程中会将全部的子进程的句柄存起来,之后进行进程间通信用。
那么 我将全部的客户端的连接存起来存成数组,每当一个客户端发送消息时,我就遍历这个客户端数组,将消息群发一遍,不久实现了聊天室了吗?
而后就,服务端代码成了这个样子web
<?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.phpwebsocket
<?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 ); } }); $server->on('close', function ($ser, $fd) { echo "client {$fd} closed\n"; }); $server->start();
再次打开html文件,多个页面进行输入观察,ok,能够了。swoole
固然,做为聊天室,我这写的也过于简陋了,界面你们本身能够写的好看一些(由于我懒的写界面)
还有,每次的发送聊天的记录,应该存起来,这样,若是有新的链接连过来的时候,先把之前的聊天记录发过去,这样,我想体验更好一些
而后,你们能够愉快的聊天了。哈哈