经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » PHP » 查看文章
Swoole跟thinkphp5结合开发WebSocket在线聊天通讯系统
来源:cnblogs  作者:程序媛的明天  时间:2019/11/5 10:32:41  对本文有异议



ThinkPHP使用Swoole需要安装 think-swoole Composer包,前提系统已经安装好了Swoole PECL 拓展*

tp5的项目根目录下执行composer命令安装think-swoole:

  1. composer require topthink/think-swoole

 

话不多说,直接上代码:

新建WebSocket.php控制器

(监听端口要确认服务器放行,宝塔环境还需要添加安全组规则)

  1. 1 <?php
  2. 2
  3. 3 namespace app\home\controller;
  4. 4 use think\swoole\Server;
  5. 5 class WebSocket extends Server
  6. 6 {
  7. 7 protected $host = '0.0.0.0'; //监听所有地址
  8. 8 protected $port = 9501; //监听9501端口
  9. 9 protected $serverType = 'socket';
  10. 10 protected $option = [
  11. 11 'worker_num'=> 4, //设置启动的Worker进程数
  12. 12 'daemonize' => false, //守护进程化(上线改为true)
  13. 13 'backlog' => 128, //Listen队列长度
  14. 14 'dispatch_mode' => 2, //固定模式,保证同一个连接发来的数据只会被同一个worker处理
  15. 15
  16. 16 //心跳检测:每60秒遍历所有连接,强制关闭10分钟内没有向服务器发送任何数据的连接
  17. 17 'heartbeat_check_interval' => 60,
  18. 18 'heartbeat_idle_time' => 600
  19. 19 ];
  20. 20
  21. 21 //建立连接时回调函数
  22. 22 public function onOpen($server,$req)
  23. 23 {
  24. 24 $fd = $req->fd;//客户端标识
  25. 25 $uid = $req->get['uid'];//客户端传递的用户id
  26. 26 $token = $req->get['token'];//客户端传递的用户登录token
  27. 27
  28. 28 //省略token验证逻辑......
  29. 29 if (!$token) {
  30. 30 $arr = array('status'=>2,'message'=>'token已过期');
  31. 31 $server->push($fd, json_encode($arr));
  32. 32 $server->close($fd);
  33. 33 return;
  34. 34 }
  35. 35 //省略给用户绑定fd逻辑......
  36. 36 echo "用户{$uid}建立了连接,标识为{$fd}\n";
  37. 37 }
  38. 38
  39. 39 //接收数据时回调函数
  40. 40 public function onMessage($server,$frame)
  41. 41 {
  42. 42 $fd = $frame->fd;
  43. 43 $message = $frame->data;
  44. 44
  45. 45 //省略通过fd查询用户uid逻辑......
  46. 46 $uid = 666;
  47. 47 $data['uid'] = $uid;
  48. 48 $data['message'] = '用户'.$uid.'发送了:'.$message;
  49. 49 $data['post_time'] = date("m/d H:i",time());
  50. 50 $arr = array('status'=>1,'message'=>'success','data'=>$data);
  51. 51
  52. 52 //仅推送给当前连接用户
  53. 53 //$server->push($fd, json_encode($arr));
  54. 54
  55. 55 //推送给全部连接用户
  56. 56 foreach($server->connections as $fd) {
  57. 57 $server->push($fd, json_encode($arr));
  58. 58 }
  59. 59 }
  60. 60
  61. 61 //连接关闭时回调函数
  62. 62 public function onClose($server,$fd)
  63. 63 {
  64. 64 echo "标识{$fd}关闭了连接\n";
  65. 65 }
  66. 66 }

 

前端演示页面:

(省略控制器判断登录状态、分配数据逻辑......)

 

  1. 1 <!DOCTYPE html>
  2. 2 <html lang="en">
  3. 3 <head>
  4. 4 <meta charset="UTF-8" />
  5. 5 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  6. 6 <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  7. 7 <title>Chat</title>
  8. 8 <link rel="stylesheet" type="text/css" href="/static/liaotian/chat.css" />
  9. 9 <script src="/static/liaotian/js/jquery.min.js"></script>
  10. 10 <script src="/static/liaotian/js/flexible.js"></script>
  11. 11 </head>
  12. 12 <body>
  13. 13 <header class="header">
  14. 14 <a class="back" href="javascript:history.back()"></a>
  15. 15 <h5 class="tit">在线聊天</h5>
  16. 16 <a href=""><div class="right">退出</div></a>
  17. 17 </header>
  18. 18
  19. 19 <!-- 聊天内容 start-->
  20. 20 <div class="message"> </div>
  21. 21 <!-- 聊天内容 end-->
  22. 22
  23. 23 <!-- 底部 start-->
  24. 24 <div class="footer">
  25. 25 <img id="setbtn" src="/static/liaotian/images/hua.png" alt="" />
  26. 26 <img src="/static/liaotian/images/xiaolian.png" alt="" />
  27. 27 <input type="text" id="msg" value="" maxlength="300">
  28. 28 <p style="background: rgb(17, 79, 142);" id="sendBtn">发送</p>
  29. 29 </div>
  30. 30 <!-- 底部 end-->
  31. 31 </body>
  32. 32 </html>
  33. 33 <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
  34. 34 <script src="https://cdn.bootcss.com/layer/3.1.0/layer.js"></script>
  35. 35 <script type="text/javascript">
  36. 36 $(function () {
  37. 37 var uid = 666;//当前用户id
  38. 38 var token = 'abcdefg';//用户token
  39. 39
  40. 40 //判断浏览器是否支持WebSocket
  41. 41 var supportsWebSockets = 'WebSocket' in window || 'MozWebSocket' in window;
  42. 42 if (supportsWebSockets) {
  43. 43 //建立WebSocket连接(ip地址换成自己主机ip)
  44. 44 var ws = new WebSocket("ws://127.0.0.1:9501?uid="+uid+"&token="+token);
  45. 45 ws.onopen = function () {
  46. 46 layer.msg('服务器连接成功',{shade:0.1,icon:1,time:600});
  47. 47 };
  48. 48 ws.onerror = function () {
  49. 49 layer.msg('服务器连接失败',{shade:0.1,icon:2,time:600});
  50. 50 };
  51. 51 ws.onmessage = function (evt) {
  52. 52 var data = $.parseJSON(evt.data);
  53. 53 //错误提示
  54. 54 if(data.status != 1){
  55. 55 layer.alert(data.message,{icon:2});
  56. 56 return;
  57. 57 }
  58. 58 //消息返回
  59. 59 if (data.status==1 && data.data.message!='') {
  60. 60 var html = "";
  61. 61 if (data.data.uid == uid) {
  62. 62 html += "<div style='word-break:break-all' class=\"show\"><div class=\"time\">"+data.data.post_time+"</div><div class=\"msg\"><img src=\""+data.data.head_img+"\" alt=\"\" /><p><i clas=\"msg_input\"></i>"+data.data.message+"</p></div></div>";
  63. 63 }else{
  64. 64 html += "<div style='word-break:break-all' class=\"send\"><div class=\"time\">"+data.data.post_time+"</div><div class=\"msg\"><img src=\""+data.data.head_img+"\" alt=\"\" /><p><i clas=\"msg_input\"></i>"+data.data.message+"</p></div></div>";
  65. 65 }
  66. 66 }
  67. 67 $(".message").append(html);
  68. 68 setTimeout(function () {
  69. 69 ($('.message').children("div:last-child")[0]).scrollIntoView();//向上滚动
  70. 70 },100);
  71. 71 };
  72. 72 ws.onclose = function (res) {
  73. 73
  74. 74 };
  75. 75 //按钮发送
  76. 76 $("#sendBtn").click(function () {
  77. 77 var contents = $("#msg").val().trim();
  78. 78 if(contents == null || contents == ""){
  79. 79 layer.msg('内容为空',{shade:0.1,icon:2,time:600});
  80. 80 return false;
  81. 81 }else{
  82. 82 ws.send(contents);
  83. 83 $("#msg").val("");
  84. 84 }
  85. 85 });
  86. 86 //回车发送
  87. 87 $("#msg").keydown(function (evel) {
  88. 88 var that = $(this);
  89. 89 if (evel.keyCode == 13) {
  90. 90 evel.cancelBubble = true;
  91. 91 evel.preventDefault();
  92. 92 evel.stopPropagation();
  93. 93 var contents = that.val().trim();
  94. 94 if(contents == null || contents == ""){
  95. 95 layer.msg('内容为空',{shade:0.1,icon:2,time:600});
  96. 96 return false;
  97. 97 }else{
  98. 98 ws.send(contents);
  99. 99 that.val("");
  100. 100 }
  101. 101 }
  102. 102 });
  103. 103 }else{
  104. 104 layer.alert("您的浏览器不支持 WebSocket!");
  105. 105 }
  106. 106 });
  107. 107 </script>
  108. 108

 

服务器移到项目根目录开启服务:

  1. php public/index.php Websocket/start

 

这里的路径,是因为我绑定了home模块为默认模块,tp5默认情况是:php public/index.php index/Websocket/start)

 

开启成功,查看端口已经被监听:

  1. lsof -i:9501

 

原文链接:http://www.cnblogs.com/a609251438/p/11794399.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号