Swoole跟thinkphp5结合开发WebSocket在线聊天通讯系统教程

栏目: PHP · 发布时间: 6年前

内容简介:tp5的项目根目录下执行composer命令安装think-swoole:话不多说,直接上代码:(监听端口要确认服务器放行,宝塔环境还需要添加安全组规则)

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" />
<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()"></a>
        <h5 class="tit">在线聊天</h5>
        <a href=""><div class="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

Swoole跟thinkphp5结合开发WebSocket在线聊天通讯系统教程

演示效果如下:

Swoole跟thinkphp5结合开发WebSocket在线聊天通讯系统教程

到了这里很多朋友想深入学习swoole和 laravel 、thinkphp,swoft微服务在使用中遇到很多困难,我为大家准备了一套精品 PHP 中高级进阶学习教程,需要可看下图详细内容,还可加入大牛学习圈子,分享tp,laravel,swoole,swoft微服务、 SQL 性能优化,分布式、高并发等教程,各种大牛都是1-7年PHP开发者,每天还有11年的架构师做课程讲解,助你进阶中高级PHP程序员,增值涨薪!

Swoole跟thinkphp5结合开发WebSocket在线聊天通讯系统教程

Swoole跟thinkphp5结合开发WebSocket在线聊天通讯系统教程

Swoole跟thinkphp5结合开发WebSocket在线聊天通讯系统教程

Swoole跟thinkphp5结合开发WebSocket在线聊天通讯系统教程

需要可看上图内容,还可加入大牛学习圈子,分享tp,laravel,swoole,swoft微服务、SQL性能优化,分布式、高并发等教程,各种大牛都是1-7年PHP开发者,每天还有11年的架构师做课程讲解,助你进阶中高级PHP程序员,增值涨薪!


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Usability for the Web

Usability for the Web

Tom Brinck、Darren Gergle、Scott D. Wood / Morgan Kaufmann / 2001-10-15 / USD 65.95

Every stage in the design of a new web site is an opportunity to meet or miss deadlines and budgetary goals. Every stage is an opportunity to boost or undercut the site's usability. Thi......一起来看看 《Usability for the Web》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具