PHP框架实现WebSocket在线聊天通讯系统


Posted in PHP onNovember 21, 2019

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

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

composer require topthink/think-swoole

话不多说,直接上代码:

新建WebSocket.php控制器:

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

<?php
namespace app\home\controller;
use think\swoole\Server;
class WebSocket extends Server
{
 protected $host = '0.0.0.0'; //监听所有地址
 protected $port = 9501; //监听9501端口
 protected $serverType = 'socket';
 protected $option = [ 
  'worker_num'=> 4, //设置启动的Worker进程数
  'daemonize' => false, //守护进程化(上线改为true)
  'backlog' => 128, //Listen队列长度
  'dispatch_mode' => 2, //固定模式,保证同一个连接发来的数据只会被同一个worker处理
  //心跳检测:每60秒遍历所有连接,强制关闭10分钟内没有向服务器发送任何数据的连接
  'heartbeat_check_interval' => 60,
  'heartbeat_idle_time' => 600
 ];
 //建立连接时回调函数
 public function onOpen($server,$req)
 {
  $fd = $req->fd;//客户端标识
  $uid = $req->get['uid'];//客户端传递的用户id
  $token = $req->get['token'];//客户端传递的用户登录token
  //省略token验证逻辑......
  if (!$token) {
   $arr = array('status'=>2,'message'=>'token已过期');
   $server->push($fd, json_encode($arr));
   $server->close($fd);
   return;
  }
  //省略给用户绑定fd逻辑......
  echo "用户{$uid}建立了连接,标识为{$fd}\n";
 }
 //接收数据时回调函数
 public function onMessage($server,$frame)
 {
  $fd = $frame->fd;
  $message = $frame->data;
  //省略通过fd查询用户uid逻辑......
  $uid = 666;
  $data['uid'] = $uid;
  $data['message'] = '用户'.$uid.'发送了:'.$message;
  $data['post_time'] = date("m/d H:i",time());
  $arr = array('status'=>1,'message'=>'success','data'=>$data);
  //仅推送给当前连接用户
  //$server->push($fd, json_encode($arr));
  //推送给全部连接用户
  foreach($server->connections as $fd) {
   $server->push($fd, json_encode($arr));
  } 
 }
 //连接关闭时回调函数
 public function onClose($server,$fd)
 {
  echo "标识{$fd}关闭了连接\n";
 }
}

前端演示页面:

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

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title>Chat</title>
<link rel="stylesheet" type="text/css" href="/static/liaotian/chat.css" rel="external nofollow" />
<script src="/static/liaotian/js/jquery.min.js"></script>
<script src="/static/liaotian/js/flexible.js"></script>
</head>
<body>
 <header class="header">
  <a class="back" href="javascript:history.back()" rel="external nofollow" ></a>
  <h5 class="tit">在线聊天</h5>
  <a href=""><div class=" rel="external nofollow" right">退出</div></a>
 </header>
 
 <!-- 聊天内容 start-->
 <div class="message"> </div>
 <!-- 聊天内容 end-->
 
 <!-- 底部 start-->
 <div class="footer">
  <img id="setbtn" src="/static/liaotian/images/hua.png" alt="" />
  <img src="/static/liaotian/images/xiaolian.png" alt="" />
  <input type="text" id="msg" value="" maxlength="300">
  <p style="background: rgb(17, 79, 142);" id="sendBtn">发送</p>
 </div>
 <!-- 底部 end-->
</body>
</html>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/layer/3.1.0/layer.js"></script>
<script type="text/javascript">
$(function () {
 var uid = 666;//当前用户id
 var token = 'abcdefg';//用户token
 
 //判断浏览器是否支持WebSocket
 var supportsWebSockets = 'WebSocket' in window || 'MozWebSocket' in window;
 if (supportsWebSockets) {
  //建立WebSocket连接(ip地址换成自己主机ip)
  var ws = new WebSocket("ws://127.0.0.1:9501?uid="+uid+"&token="+token);
  ws.onopen = function () {
   layer.msg('服务器连接成功',{shade:0.1,icon:1,time:600});
  };
  ws.onerror = function () {
   layer.msg('服务器连接失败',{shade:0.1,icon:2,time:600});
  };
  ws.onmessage = function (evt) {
   var data = $.parseJSON(evt.data);
   //错误提示
   if(data.status != 1){
    layer.alert(data.message,{icon:2});
    return;
   }
   //消息返回
   if (data.status==1 && data.data.message!='') {
    var html = "";
    if (data.data.uid == uid) {
     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>";
    }else{
     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>";
    }
   }
   $(".message").append(html);
   setTimeout(function () {
    ($('.message').children("div:last-child")[0]).scrollIntoView();//向上滚动
   },100);
  };
  ws.onclose = function (res) {
   
  };
  //按钮发送
  $("#sendBtn").click(function () {
   var contents = $("#msg").val().trim();
   if(contents == null || contents == ""){
    layer.msg('内容为空',{shade:0.1,icon:2,time:600});   
    return false;
   }else{
    ws.send(contents);
    $("#msg").val("");
   }
  });
  //回车发送
  $("#msg").keydown(function (evel) {
   var that = $(this);
   if (evel.keyCode == 13) {
    evel.cancelBubble = true;
    evel.preventDefault();
    evel.stopPropagation();
    var contents = that.val().trim();
    if(contents == null || contents == ""){
     layer.msg('内容为空',{shade:0.1,icon:2,time:600});    
     return false;
    }else{
     ws.send(contents);
     that.val("");
    }
   }
  });
 }else{
  layer.alert("您的浏览器不支持 WebSocket!");
 }
});
</script>

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

php public/index.php Websocket/start

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

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

lsof -i:9501

很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家 ,需要 请戳这里

总结

以上所述是小编给大家介绍的PHP框架实现WebSocket在线聊天通讯系统,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

PHP 相关文章推荐
PHP设计聊天室步步通
Oct 09 PHP
计算2000年01月01日起到指定日的天数
Oct 09 PHP
php的一个登录的类 [推荐]
Mar 16 PHP
PHP5与MySQL数据库操作常用代码 收集
Mar 21 PHP
php中将时间差转换为字符串提示的实现代码
Aug 08 PHP
PHP爬虫之百万级别知乎用户数据爬取与分析
Jan 22 PHP
PHP session会话操作技巧小结
Sep 27 PHP
PHP SFTP实现上传下载功能
Jul 26 PHP
php实现的redis缓存类定义与使用方法示例
Aug 09 PHP
在云虚拟主机部署thinkphp5项目的步骤详解
Dec 21 PHP
Yii框架学习笔记之session与cookie简单操作示例
Apr 30 PHP
php设计模式之适配器模式实例分析【星际争霸游戏案例】
Apr 07 PHP
PHP读取Excel内的图片(phpspreadsheet和PHPExcel扩展库)
Nov 19 #PHP
使用PHP开发留言板功能
Nov 19 #PHP
关于Laravel参数验证的一些疑与惑
Nov 19 #PHP
php传值和传引用的区别点总结
Nov 19 #PHP
php 使用 __call实现重载功能示例
Nov 18 #PHP
PHP中通过getopt解析GNU C风格命令行选项
Nov 18 #PHP
php 多继承的几种常见实现方法示例
Nov 18 #PHP
You might like
《心理测量者3》剧场版动画预告
2020/03/02 日漫
PHP 计算代码执行耗时的代码修正网上普遍错误
2011/05/14 PHP
PHP实现提取一个图像文件并在浏览器上显示的代码
2012/10/06 PHP
php微信公众平台示例代码分析(二)
2016/12/06 PHP
PHP实现二维数组去重功能示例
2017/01/12 PHP
PHP微信企业号开发之回调模式开启与用法示例
2017/11/25 PHP
PHP基于DateTime类解决Unix时间戳与日期互转问题【针对1970年前及2038年后时间戳】
2018/06/13 PHP
QUnit jQuery的TDD框架
2010/11/04 Javascript
js 判断脚本加载完毕的代码
2011/07/13 Javascript
基于jquery二维码生成插件qrcode
2017/01/07 Javascript
微信小程序-横向滑动scroll-view隐藏滚动条
2017/04/20 Javascript
AngularJS动态绑定ng-options的ng-model实例代码
2017/06/21 Javascript
在create-react-app中使用css modules的示例代码
2018/07/31 Javascript
一些你可能不熟悉的JS知识点总结
2019/03/15 Javascript
vue setInterval 定时器失效的解决方式
2020/07/30 Javascript
vue 获取url里参数的两种方法小结
2020/11/12 Javascript
vue祖孙组件之间的数据传递案例
2020/12/07 Vue.js
[01:27:30]LGD vs Newbee 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/19 DOTA
[52:26]完美世界DOTA2联赛决赛 FTD vs Phoenix 第一场 11.08
2020/11/11 DOTA
编写Python脚本批量下载DesktopNexus壁纸的教程
2015/05/06 Python
pyQt4实现俄罗斯方块游戏
2018/06/26 Python
python保存网页图片到本地的方法
2018/07/24 Python
值得收藏,Python 开发中的高级技巧
2018/11/23 Python
详解python算法之冒泡排序
2019/03/05 Python
详解用python自制微信机器人,定时发送天气预报
2019/03/25 Python
react+django清除浏览器缓存的几种方法小结
2019/07/17 Python
使用Python调取任意数字资产钱包余额功能
2019/08/15 Python
python实现ftp文件传输系统(案例分析)
2020/03/20 Python
LODI女鞋在线商店:阿利坎特的鞋类品牌
2019/02/15 全球购物
bonprix荷兰网上商店:便宜的服装、鞋子和家居用品
2020/07/04 全球购物
高三自我鉴定
2013/10/23 职场文书
电大本科自我鉴定
2014/02/05 职场文书
大学生个人求职口试自我评价
2014/02/16 职场文书
怎样写好自我评价呢?
2014/02/16 职场文书
内勤岗位职责
2015/02/10 职场文书
MySQL中的引号和反引号的区别与用法详解
2021/10/24 MySQL