WebSocket+微信小程序一对一聊天

前言

一、搭建服务端

在我们的宝塔中创建一个以 .php 结尾的文件,将下面的内容放进去,

<?php
 
//创建WebSocket Server对象,监听0.0.0.0:9502端口
$ws = new SwooleWebSocketServer(0.0.0.0, 9502);
 
//实例化Redis
$redis = new Redis();
//对redis进行连接
$redis->connect(127.0.0.1,6379);

$ws->set([
    heartbeat_idle_time      => 600, // 表示一个连接如果600秒内未向服务器发送任何数据,此连接将被强制关闭
    heartbeat_check_interval => 60,  // 表示每60秒遍历一次
    daemonize => true               //  守护进程
]);
 
//监听WebSocket连接打开事件
$ws->on(Open, function ($ws, $request) {
    //向小程序端进行一个连接返回,告知用户已经连接上服务器,返回值需要转为json数据格式
    $ws->push($request->fd, json_encode([msg=>用户已连接],true));
});
 
//监听WebSocket消息事件
$ws->on(Message, function ($ws, $frame) use ($redis) {
   $res = json_decode($frame->data,true);
    //print_r($res);
    if($res[type]==article)$ws->push($frame->fd,json_encode([msg=>心跳监测]));
    if($res[type]==open)$redis->set($res[me],$frame->fd);
    if($res[type]==send){
        $to = $redis->get($res[to]);
        $data = [
            msg=>$res[msg],
            style=>$res[me],
            error_code=>0
        ];
        $ws->push($to,json_encode($data));
    }
});
 
//监听WebSocket连接关闭事件
$ws->on(Close, function ($ws, $fd) {
    echo "client-{$fd} is closed
";
});
 
$ws->start();

 二、搭建客服端

可以在onLoad中直接写入,也可以封装起来,通过wx.connectSocket来建立客服端和服务端的一个连接

然后创建一个心跳监测方法,自动向服务端发送状态。

webSocketXin(time = 3000, status = true) {
    var timing;
    if (status == true) {
      timing = setInterval(function () {
        console.log("当前心跳已重新连接");
        //循环执行代码
        wx.sendSocketMessage({
          data: JSON.stringify({
            type: active
          }),
          fail(res) {
            //关闭连接
            wx.closeSocket();
            //提示
            wx.showToast({
              title: 当前聊天已断开,
              icon: none
            });
            clearInterval(timing);
            console.log("当前心跳已关闭");
          }
        });
      }, time) //循环时间,注意不要超过1分钟
    } else {
      //关闭定时器
      clearInterval(timing);
      console.log("当前心跳已关闭");
    }
  },

创建一个发送方法向服务端发送消息,并且使用wx.onSocketMessage监听服务端收到的消息,将消息入栈存入我们创建好的空数组。

//发送信息
send:function(res){
    //调用向服务器发送信息函数
    wx.sendSocketMessage({
        data : res
    })
}
 
//获取输入框信息并发送
sendMyMsg:function(option){
    let myMsg = option.detail.value.text;
    let msg = {
        me : user,    //我是谁
        to : server,    //发送给谁
        type : send,    //当前状态
        data : myMsg    //发送信息
    }
    this.send(JSON.stringify(msg));    //调用发送方法,向服务器发送数据
    let data = this.data.list;    //将页面data内的数组records进行调用
    //将用户名称及发送信息追加到数组中
    data.push({
        user : msg.my,
        msg : myMsg
    })
    //进行数据传递
    this.setData({
        records : data
    })
}
 
//接收服务器返回消息
serverMsg:function(){
    //调用接收函数,接收服务器返回数据
    wx.onSocketMessage((result)=>{
        //因为在数据库中返回的数据为json数据格式,因此我们需要在前台进行转义
        let parseMsg = JSON.parse(result.data);
        let data = _this.data.data;    //调用页面data内的数组records
        //接收到的数据追加到数组中
        data.push({
            user : parseMsg.user,
            msg : parseMsg.msg
        })
        //数据传递
        this.setData({
            list: data
        })
    })
}

在wxml页面进行循环数组,将监听到的消息数据展示出来

<l-input label="消息" placeholder="请输入要发送的消息" bind:lininput=getMsg style="float: left;" />
<l-button type=success bind:lintap="send">发送</l-button>


<view style="clear: left;">
  <block wx:for="{
         
  {list}}" wx:key="index">
    <view wx:if="{
         
  {item.style==undefined}}">
      {
         
  {item.msg}}
    </view>
    <view wx:else>
<!-- 判断条件,判罚是否为自己发送的内容,是在右边出现,不是在左边出现 -->
      <view wx:if="{
         
  {item.style==***}}">
        <view style="text-align: right;">
          {
         
  {item.msg}}:{
         
  {item.style}}
        </view>
      </view>
      <view wx:else style="text-align: left;">
        {
         
  {item.style}}:{
         
  {item.msg}}
      </view>
    </view>
  </block>
</view>
经验分享 程序员 微信小程序 职场和发展