五分钟教你写超简单的swoole聊天室

移动开发
那么 我将所有的客户端的链接存起来存成数组,每当一个客户端发送消息时,我就遍历这个客户端数组,将消息群发一遍,不久实现了聊天室了吗?

原本我是准备接着写我那个多进程教程的,今天心血来潮想看看swoole的websocket,

swoole-1.7.9 增加了内置的websocket服务器支持,通过几行PHP代码就可以写出一个异步非阻塞多进程的WebSocket服务器。

swoole_websocket_server 继承自 swoole_http_server,如果设置了onRequest回调,websocket服务器也可以同时作为http服务器。

  1. $server = new swoole_websocket_server("0.0.0.0"9501); 
  2.  
  3. $server->on('open', function (swoole_websocket_server $server, $request) { 
  4. echo "server: handshake success with fd{$request->fd}\n"
  5. }); 
  6.  
  7. $server->on('message', function (swoole_websocket_server $server, $frame) { 
  8. echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n"
  9. $server->push($frame->fd, "this is server"); 
  10. }); 
  11.  
  12. $server->on('close', function ($ser, $fd) { 
  13. echo "client {$fd} closed\n"
  14. }); 
  15.  
  16. $server->start(); 

我看了看官网的demo,觉得看起来很简单嘛,

  1. <?php 
  2. //官网demo 
  3. $server = new swoole_websocket_server("0.0.0.0", 9501); 
  4.  
  5. $server->on('open', function (swoole_websocket_server $server, $request) { 
  6. echo "server: handshake success with fd{$request->fd}\n";//$request->fd 是客户端id 
  7. }); 
  8.  
  9. $server->on('message', function (swoole_websocket_server $server, $frame) { 
  10. echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n"; 
  11. $server->push($frame->fd, "this is server");//$frame->fd 是客户端id,$frame->data是客户端发送的数据 
  12. //服务端向客户端发送数据是用 $server->push( '客户端id' , '内容') 
  13. }); 
  14.  
  15. $server->on('close', function ($ser, $fd) { 
  16. echo "client {$fd} closed\n"; 
  17. }); 
  18.  
  19. $server->start(); 

我就是喜欢这种简单易懂的demo ,每行代码意思一看就明白

服务端有了,我找点客户端的js代码

火狐的MDN

  1. <!DOCTYPE html> 
  2. <html> 
  3. <head> 
  4. <title></title> 
  5. <meta charset="UTF-8"
  6. <script type="text/javascript"
  7. var exampleSocket = new WebSocket("ws://0.0.0.0:9501"); 
  8. exampleSocket.onopen = function (event) { 
  9. exampleSocket.send("亲爱的服务器!我连上你啦!"); 
  10. }; 
  11. exampleSocket.onmessage = function (event) { 
  12. console.log(event.data); 
  13. </script> 
  14. </head> 
  15. <body> 
  16. <input type="text" id="content"
  17. <button onclick="exampleSocket.send( document.getElementById('content').value )">发送</button> 
  18. </body> 
  19. </html> 

***命令行运行php文件,之后浏览器打开html文件,

F12打开调试界面看console,ok , 没有问题

这个时候我突然想到一个事情,因为我做多进程的那个教程里,在主进程中会将所有的子进程的句柄存起来,以后进行进程间通讯用。

那么 我将所有的客户端的链接存起来存成数组,每当一个客户端发送消息时,我就遍历这个客户端数组,将消息群发一遍,不久实现了聊天室了吗?

然后就,服务端代码成了这个样子

  1. <?php 
  2. $map = array();//客户端集合 
  3. $server = new swoole_websocket_server("0.0.0.0"9501); 
  4.  
  5. $server->on('open', function (swoole_websocket_server $server, $request) { 
  6. global $map;//客户端集合 
  7. $map[$request->fd] = $request->fd;//***连上时存起来 
  8. }); 
  9.  
  10. $server->on('message', function (swoole_websocket_server $server, $frame) { 
  11. global $map;//客户端集合 
  12. $data = $frame->data; 
  13. foreach($map as $fd){ 
  14. $server->push($fd , $data);//循环广播 
  15. }); 
  16.  
  17. $server->on('close', function ($ser, $fd) { 
  18. echo "client {$fd} closed\n"
  19. }); 
  20.  
  21. $server->start(); 

哈哈 , 我觉得这样就大功告成了,结果发现自己是 图样图森破

大家可以自己试试,运行php后 , 浏览器打开两个页面,看看console.log的内容是什么

运行良好,可是并没有实现我们说的那种聊天效果。

找找原因吧。

我***反映看看$map里面是什么,就输出看看,结果发现这个map里面只有一个元素。

唉,不对啊,我这是全局变量,难道不应该是有几个客户端链接,就有几个元素吗?

这是怎么回事啊,竟然没有保存到所有客户端id?

到了这一步,我解决不了map变量的这个问题了,然后我就想看看那个fd是什么东西,

老规矩 var_dump输出 , 发现fd就是 int类型的数字,并且是自增的

这好办了,不就是数字嘛

于是呼,我就这样做

变量存不了,我搞不定,我存文本里嘛。

最终版 websocket.php

  1. <?php 
  2.  
  3. $server = new swoole_websocket_server("0.0.0.0"9501); 
  4.  
  5. $server->on('open', function (swoole_websocket_server $server, $request) { 
  6. file_put_contents( __DIR__ .'/log.txt' , $request->fd); 
  7. }); 
  8.  
  9. $server->on('message', function (swoole_websocket_server $server, $frame) { 
  10. global $client; 
  11. $data = $frame->data; 
  12. $m = file_get_contents( __DIR__ .'/log.txt'); 
  13. for ($i=1 ; $i<= $m ; $i++) { 
  14. echo PHP_EOL . ' i is ' . $i . ' data is '.$data . ' m = ' . $m; 
  15. $server->push($i, $data ); 
  16.  
  17. }); 
  18.  
  19. $server->on('close', function ($ser, $fd) { 
  20. echo "client {$fd} closed\n"
  21. }); 
  22.  
  23. $server->start(); 

再次打开html文件,多个页面进行输入观察,ok,可以了。

当然,作为聊天室,我这写的也过于简陋了,界面大家自己可以写的好看一些(因为我懒的写界面)

还有,每次的发送聊天的记录,应该存起来,这样,如果有新的连接连过来的时候,先把以前的聊天记录发过去,这样,我想体验更好一些

然后,大家可以愉快的聊天了。哈哈

责任编辑:chenqingxiang
相关推荐

2015-07-06 10:42:18

PHP聊天室应用

2023-02-10 08:16:48

WebSocket简易聊天室

2011-12-15 11:11:51

JavaNIO

2009-11-04 16:13:18

ADO.NET数据表

2022-07-26 14:53:10

WebSocket网络通信协议

2009-11-16 10:53:30

Oracle Hint

2022-08-22 08:32:17

招聘函数string

2020-12-07 09:01:58

幂等系统f(f(x)) =f(

2021-01-18 05:59:21

开发桌面版应用技术热点

2020-06-16 08:47:53

磁盘

2021-08-01 21:38:07

网页点灯网关

2019-08-09 10:33:36

开发技能代码

2021-06-07 09:51:22

原型模式序列化

2009-11-05 14:53:54

Visual Stud

2009-10-22 16:18:19

Oracle表空间

2021-10-19 07:27:08

HTTP代理网络

2023-05-27 21:13:34

FlaskURL装饰器

2023-09-18 15:49:40

Ingress云原生Kubernetes

2022-10-12 23:02:49

Calcite异构数据框架

2009-11-16 09:53:56

PHP上传类
点赞
收藏

51CTO技术栈公众号