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与javascript对多项选择的处理
Oct 09 PHP
PHP统计目录下的文件总数及代码行数(去除注释及空行)
Jan 17 PHP
PHP中文件读、写、删的操作(PHP中对文件和目录操作)
Mar 06 PHP
PHP数组传递是值传递而非引用传递概念纠正
Jan 31 PHP
基于PHP一些十分严重的缺陷详解
Jun 03 PHP
解析php做推送服务端实现ios消息推送
Jul 01 PHP
PHP仿博客园 个人博客(1) 数据库与界面设计
Jul 05 PHP
PHPExcel内存泄漏问题解决方法
Jan 23 PHP
php隐藏实际地址的文件下载方法
Apr 18 PHP
php对象和数组相互转换的方法
May 12 PHP
学习php设计模式 php实现享元模式(flyweight)
Dec 07 PHP
Laravel框架路由设置与使用示例
Jun 12 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
php数组函数序列之in_array() - 查找数组中是否存在指定值
2011/11/07 PHP
PHP中通过fopen()函数访问远程文件示例
2014/11/18 PHP
php实现统计二进制中1的个数算法示例
2018/01/23 PHP
使用PHPUnit进行单元测试并生成代码覆盖率报告的方法
2019/03/08 PHP
Javascript实例教程(19) 使用HoTMetal(4)
2006/12/23 Javascript
node.js使用nodemailer发送邮件实例
2014/03/10 Javascript
js实现的牛顿摆效果
2015/03/31 Javascript
js判断手机访问或者PC的几个例子(常用于手机跳转)
2015/12/15 Javascript
javascript创建对象、对象继承的实用方式详解
2016/03/08 Javascript
jQuery实现右下角可缩放大小的层完整实例
2016/06/20 Javascript
js cookie实现记住密码功能
2017/01/17 Javascript
js实现滑动到页面底部自动加载更多功能
2017/02/15 Javascript
值得收藏的vuejs安装教程
2017/11/21 Javascript
微信小程序实现上传多张图片、删除图片
2020/07/29 Javascript
python通过wxPython打开一个音频文件并播放的方法
2015/03/25 Python
Python KMeans聚类问题分析
2018/02/23 Python
对pandas读取中文unicode的csv和添加行标题的方法详解
2018/12/12 Python
python 获得任意路径下的文件及其根目录的方法
2019/02/16 Python
Django Sitemap 站点地图的实现方法
2019/04/29 Python
下载官网python并安装的步骤详解
2019/10/12 Python
Python爬虫requests库多种用法实例
2020/05/28 Python
使用python把xmind转换成excel测试用例的实现代码
2020/10/12 Python
使用CSS3代码绘制可爱的Hello Kitty猫
2016/08/03 HTML / CSS
使用canvas来完成线性渐变和径向渐变的功能的方法示例
2019/07/25 HTML / CSS
canvas 基础之图像处理的使用
2020/04/10 HTML / CSS
松本清官方海外旗舰店:日本最大的药妆连锁店
2017/11/21 全球购物
德国亚马逊官方网站:Amazon.de
2020/11/15 全球购物
优秀毕业大学生推荐信
2013/11/13 职场文书
三八红旗集体先进事迹材料
2014/05/22 职场文书
走群众路线学习笔记
2014/11/06 职场文书
2015年学校教务处工作总结
2015/05/11 职场文书
幼儿园六一主持词
2015/06/30 职场文书
保护环境建议书作文400字
2015/09/14 职场文书
加强党性修养心得体会
2016/01/21 职场文书
职场新人刚入职工作总结该怎么写?
2019/05/15 职场文书
selenium.webdriver中add_argument方法常用参数表
2021/04/08 Python