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中用PDO查询Mysql来避免SQL注入风险的方法
Apr 25 PHP
php实现根据IP地址获取其所在省市的方法
Apr 30 PHP
常用的php图片处理类(水印、等比缩放、固定高宽)分享
Jun 19 PHP
PHP register_shutdown_function()函数的使用示例
Jun 23 PHP
PHP利用APC模块实现大文件上传进度条的方法
Oct 29 PHP
ThinkPHP Where 条件中常用表达式示例(详解)
Mar 31 PHP
PHP检查网站是否宕机的方法示例
Jul 24 PHP
PHP验证码无法显示的原因及解决办法
Aug 11 PHP
php使用scandir()函数扫描指定目录下所有文件示例
Jun 08 PHP
laravel实现按月或天或小时统计mysql数据的方法
Oct 09 PHP
PHP cookie与session会话基本用法实例分析
Nov 18 PHP
YII2框架中查询生成器Query()的使用方法示例
Mar 18 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后台程序与Javascript的两种交互方式
2009/10/25 PHP
php数据入库前清理 注意php intval与mysql的int取值范围不同
2010/12/12 PHP
关于file_get_contents返回为空或函数不可用的解决方案
2013/06/24 PHP
php在数组中查找指定值的方法
2015/03/17 PHP
php和nginx交互实例讲解
2019/09/24 PHP
js 实现在离开页面时提醒未保存的信息(减少用户重复操作)
2013/01/16 Javascript
javascript通过navigator.userAgent识别各种浏览器
2013/10/25 Javascript
基于jQuery实现的文字按钮表单特效整理
2014/12/07 Javascript
JavaScript模拟深蓝vs卡斯帕罗夫的国际象棋对局示例
2015/04/22 Javascript
BootStrap 弹出层代码
2017/02/09 Javascript
vue移动端UI框架实现QQ侧边菜单组件
2018/03/09 Javascript
[01:18:43]2014 DOTA2华西杯精英邀请赛5 24 iG VS DK
2014/05/25 DOTA
[35:34]Liquid vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
python连接mysql并提交mysql事务示例
2014/03/05 Python
Python函数参数类型*、**的区别
2015/04/11 Python
在Python 3中实现类型检查器的简单方法
2015/07/03 Python
Python实现类似jQuery使用中的链式调用的示例
2016/06/16 Python
Pycharm之快速定位到某行快捷键的方法
2019/01/20 Python
python图像处理入门(一)
2019/04/04 Python
html5给汉字加拼音加进度条的实现代码
2020/04/07 HTML / CSS
HTML5播放实现rtmp流直播
2020/06/16 HTML / CSS
澳大利亚旅游网站:Lastminute
2017/08/07 全球购物
抽象方法、抽象类怎样声明
2014/10/25 面试题
高中毕业生自我鉴定范文
2013/09/26 职场文书
实习生体会的自我评价范文
2013/11/28 职场文书
质检员岗位职责
2013/12/17 职场文书
期末评语大全
2014/05/04 职场文书
大学生求职信
2014/06/17 职场文书
校园游戏活动新闻稿
2014/10/15 职场文书
初中家长评语和期望
2014/12/26 职场文书
大学推普周活动总结
2015/05/07 职场文书
中国汉字听写大会观后感
2015/06/02 职场文书
外出学习心得体会范文
2016/01/18 职场文书
详解MySQL InnoDB存储引擎的内存管理
2021/04/08 MySQL
go 实现简易端口扫描的示例
2021/05/22 Golang
开机音效回归! Windows 11重新引入开机铃声
2021/11/21 数码科技