关于webscoket在小程序与web端的实时通讯(PHP webscoket)

本文集合小程序端,web端,PHP服务器
涉及到 vue.js,webscoket , php
直接开始吧

一、websocket的介绍

1.1 websocket概念

websocket是HTML5中新引进的一种协议,它是一种协议就像(HTTP,FTP在tcp/ip协议栈中属于应用层)而不是简单的一个函数。它本身及基于TCP协议的一种新的协议。
在这里插入图片描述
二、PHP WEBsocket

<?php

/**
 * Socket服务器
 * 
 */
class SocketServer
{
    private $sockets; //连接池
    private $master;
    private $handshake;

    /**
     * @param $address
     * @param $port
     */
    public function run($address, $port)
    {
        //配置错误级别、运行时间、刷新缓冲区
        echo iconv('UTF-8', 'GBK', "欢迎来到PHP Socket测试服务。 \n");
        error_reporting(0);
        set_time_limit(0);
        ob_implicit_flush();

        //创建socket
        $this->master = $this->_connect($address, $port);
        $this->sockets[] = $this->master;

        //运行socket
        while (true) {
            $sockets = $this->sockets;
            $write = NULL;
            $except = NULL;
            socket_select($sockets, $write, $except, NULL); //$write,$except传引用
            foreach ($sockets as $socket) {
                if ($socket == $this->master) {
                    $client = socket_accept($socket);
                    $this->handshake = false;
                    if ($client) {
                        $this->sockets[] = $client; //加入连接池
                    }
                } else {
                    //接收信息
                    $bytes = @socket_recv($socket, $buffer, 2048, 0);
                    if ($bytes <= 6) {
                        $this->_disConnect($socket);
                        continue;
                    };

                    //处理信息
                    if (!$this->handshake) {
                        $this->_handshake($socket, $buffer);
                    } else {
                        $buffer = $this->_decode($buffer);
                        $this->_sendMsg($buffer, $socket);
                    }
                }

            }
        }
    }

    /**
     * 创建socket连接
     * @param $address
     * @param $port
     * @return resource
     */
    private function _connect($address, $port)
    {
        //创建socket
        $master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
        or die("socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n");
        socket_bind($master, $address, $port)
        or die("socket_bind() failed: reason: " . socket_strerror(socket_last_error($master)) . "\n");
        socket_listen($master, 5)
        or die("socket_listen() failed: reason: " . socket_strerror(socket_last_error($master)) . "\n");
        return $master;
    }

    /**
     * 握手动作
     * @param $socket
     * @param $buffer
     */
    private function _handshake($socket, $buffer)
    {
        //握手动作信息
        $buf = substr($buffer, strpos($buffer, 'Sec-WebSocket-Key:') + 18);
        $key = trim(substr($buf, 0, strpos($buf, "\r\n")));
        $new_key = base64_encode(sha1($key . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));
        $new_message = "HTTP/1.1 101 Switching Protocols\r\n";
        $new_message .= "Upgrade: websocket\r\n";
        $new_message .= "Sec-WebSocket-Version: 13\r\n";
        $new_message .= "Connection: Upgrade\r\n";
        $new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n";

        //记录握手动作
        socket_write($socket, $new_message, strlen($new_message));
        $this->handshake = true;
    }

    /**
     * 断开socket连接
     * @param $socket
     */
    private function _disConnect($socket)
    {
        $index = array_search($socket, $this->sockets);
        socket_close($socket);
        if ($index >= 0) {
            array_splice($this->sockets, $index, 1);
        }
    }

    /**
     * 发送信息
     * @param $buffer
     * @param $client
     */
    private function _sendMsg($buffer, $client)
    {
        $send_buffer = $this->_frame(json_encode($buffer));
        foreach ($this->sockets as $socket) {
            if ($socket != $this->master && $socket != $client) { //广播发送(除了自己)
                socket_write($socket, $send_buffer, strlen($send_buffer));
            }
        }
    }

    /**
     * 解析数据帧
     * @param $buffer
     * @return null|string
     */
    private function _decode($buffer)
    {
        $len = $masks = $data = $decoded = null;
        $len = ord($buffer[1]) & 127;
        if ($len === 126) {
            $masks = substr($buffer, 4, 4);
            $data = substr($buffer, 8);
        } else if ($len === 127) {
            $masks = substr($buffer, 10, 4);
            $data = substr($buffer, 14);
        } else {
            $masks = substr($buffer, 2, 4);
            $data = substr($buffer, 6);
        }
        for ($index = 0; $index < strlen($data); $index++) {
            $decoded .= $data[$index] ^ $masks[$index % 4];
        }
        return $decoded;
    }

    /**
     * 处理返回帧
     * @param $buffer
     * @return string
     */
    private function _frame($buffer)
    {
        $len = strlen($buffer);
        if ($len <= 125) {
            return "\x81" . chr($len) . $buffer;
        } else if ($len <= 65535) {
            return "\x81" . chr(126) . pack("n", $len) . $buffer;
        } else {
            return "\x81" . char(127) . pack("xxxxN", $len) . $buffer;
        }
    }
}

$sc = new SocketServer();
$sc->run('127.0.0.1', 2046); //注意run()第一个参数是本地ip地址,放在服务器里就应该是服务器的局域网地址(不能用服务器公网地址)

运行PHP命令:PHP -q filename.php
这样一个webscoket服务就建立好了。
现在介绍一下“workerman”
在这里插入图片描述
http://doc.workerman.net/install/install.html
----------------------后期会做应用教程实例---------------------------------
接下来我们做小程序端

三、微信小程序端

app.js

//app.js
App({
  globalData: {
    userInfo: null,
    socketStatus: 'closed',  //必要
    navHeight: 0
  },
  
  onLaunch: function () {
   
    var that = this;
    if (that.globalData.socketStatus === 'closed') {
      that.openSocket();
    }
  openSocket() {
    //打开时的动作
    wx.onSocketOpen(() => {
      console.log('WebSocket 已连接')
      this.globalData.socketStatus = 'connected';
      // this.sendMessage();
    })
    //断开时的动作
    wx.onSocketClose(() => {
      console.log('WebSocket 已断开')
      this.globalData.socketStatus = 'closed'
    })
    //报错时的动作
    wx.onSocketError(error => {
      console.error('socket error:', error)
    })
    // 监听服务器推送的消息
    wx.onSocketMessage(message => {
      //把JSONStr转为JSON
      message = message.data.replace(" ", "");
      if (typeof message != 'object') {
        message = message.replace(/\ufeff/g, ""); //重点
        var jj = JSON.parse(message);
        message = jj;
      }
      console.log("【websocket监听到消息】内容如下:");
      console.log(message);
    })
    // 打开信道
    wx.connectSocket({
      url: "ws://" + "127.0.0.1" + ":8001",
    })
  },
  //关闭信道
  closeSocket() {
    if (this.globalData.socketStatus === 'connected') {
      wx.closeSocket({
        success: () => {
          this.globalData.socketStatus = 'closed'
        }
      })
    }
  },

  
 
})

调用:

 wx.sendSocketMessage({
            data: JSON.stringify(要发送的内容),
            success: function (e) {
              wx.lin.showMessage({
                type: 'success',
                content: '成功'
              })
              console.log('ok')
            },
            fail: function (e) {
              wx.lin.showMessage({
                type: 'error',
                content: '失败'
              })
            },
            complete: function (e) {
              wx.lin.showMessage({
                type: 'success',
                content: '成功'
              })
              console.log(e)
            }
          })

—以后还会更新(封装以及心跳机制等)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值