ThinkPHP5结合Swoole开发实现WebSocket在线聊天

网友投稿 591 2022-06-17


ThinkPHP使用

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

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

composer require topthink/think-swoole

安装成功:

代码如下

新建WebSocket.php控制器:

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

  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";

  }

}

前端演示页面:

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

Chat             在线聊天     退出

           
                            发送

  
  

$(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 += ""+data.data.post_time+"

"+data.data.message+"

";

        }else{

          html += ""+data.data.post_time+"

"+data.data.message+"

";

        }

      }

      $(".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!");

  }

});

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

php public/index.php Websocket/start

这里的路径,是因为我绑定了home模块为默认模块,tp5默认情况是:

php public/index.php index/Websocket/start

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

lsof -i:9501

服务器监听如下:

用户每刷新重连一次,fd标识都会改变。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

标签:安全
上一篇:浅析 PHP7 底层运行机制(浅析是什么意思)
下一篇:PHP 数组和字符串互相转换实现方法(php菜鸟教程)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~