php实现websocket实时消息推送


Posted in PHP onMarch 30, 2018

php实现websocket实时消息推送,供大家参考,具体内容如下

php实现websocket实时消息推送

SocketService.php

<?php
/**
 * Created by xwx
 * Date: 2017/10/18
 * Time: 14:33
 */

class SocketService
{
  private $address = '0.0.0.0';
  private $port = 8083;
  private $_sockets;
  public function __construct($address = '', $port='')
  {
      if(!empty($address)){
        $this->address = $address;
      }
      if(!empty($port)) {
        $this->port = $port;
      }
  }

  public function service(){
    //获取tcp协议号码。
    $tcp = getprotobyname("tcp");
    $sock = socket_create(AF_INET, SOCK_STREAM, $tcp);
    socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1);
    if($sock < 0)
    {
      throw new Exception("failed to create socket: ".socket_strerror($sock)."\n");
    }
    socket_bind($sock, $this->address, $this->port);
    socket_listen($sock, $this->port);
    echo "listen on $this->address $this->port ... \n";
    $this->_sockets = $sock;
  }

  public function run(){
    $this->service();
    $clients[] = $this->_sockets;
    while (true){
      $changes = $clients;
      $write = NULL;
      $except = NULL;
      socket_select($changes, $write, $except, NULL);
      foreach ($changes as $key => $_sock){
        if($this->_sockets == $_sock){ //判断是不是新接入的socket
          if(($newClient = socket_accept($_sock)) === false){
            die('failed to accept socket: '.socket_strerror($_sock)."\n");
          }
          $line = trim(socket_read($newClient, 1024));
          $this->handshaking($newClient, $line);
          //获取client ip
          socket_getpeername ($newClient, $ip);
          $clients[$ip] = $newClient;
          echo "Client ip:{$ip}  \n";
          echo "Client msg:{$line} \n";
        } else {
          socket_recv($_sock, $buffer, 2048, 0);
          $msg = $this->message($buffer);
          //在这里业务代码
          echo "{$key} clinet msg:",$msg,"\n";
          fwrite(STDOUT, 'Please input a argument:');
          $response = trim(fgets(STDIN));
          $this->send($_sock, $response);
          echo "{$key} response to Client:".$response,"\n";
        }
      }
    }
  }

  /**
   * 握手处理
   * @param $newClient socket
   * @return int 接收到的信息
   */
  public function handshaking($newClient, $line){

    $headers = array();
    $lines = preg_split("/\r\n/", $line);
    foreach($lines as $line)
    {
      $line = chop($line);
      if(preg_match('/\A(\S+): (.*)\z/', $line, $matches))
      {
        $headers[$matches[1]] = $matches[2];
      }
    }
    $secKey = $headers['Sec-WebSocket-Key'];
    $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
    $upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
      "Upgrade: websocket\r\n" .
      "Connection: Upgrade\r\n" .
      "WebSocket-Origin: $this->address\r\n" .
      "WebSocket-Location: ws://$this->address:$this->port/websocket/websocket\r\n".
      "Sec-WebSocket-Accept:$secAccept\r\n\r\n";
    return socket_write($newClient, $upgrade, strlen($upgrade));
  }

  /**
   * 解析接收数据
   * @param $buffer
   * @return null|string
   */
  public function message($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 $newClinet 新接入的socket
   * @param $msg  要发送的数据
   * @return int|string
   */
  public function send($newClinet, $msg){
    $msg = $this->frame($msg);
    socket_write($newClinet, $msg, strlen($msg));
  }

  public function frame($s) {
    $a = str_split($s, 125);
    if (count($a) == 1) {
      return "\x81" . chr(strlen($a[0])) . $a[0];
    }
    $ns = "";
    foreach ($a as $o) {
      $ns .= "\x81" . chr(strlen($o)) . $o;
    }
    return $ns;
  }

  /**
   * 关闭socket
   */
  public function close(){
    return socket_close($this->_sockets);
  }
}

$sock = new SocketService();
$sock->run();

web.html

<!doctype html>
<html lang="en">
 <head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, user-scalable=no">
 <title>websocket</title>
 </head>
 <body>
 <input id="text" value="">
 <input type="submit" value="send" onclick="start()">
 <input type="submit" value="close" onclick="close()">
<div id="msg"></div>
 <script>
 /**
 0:未连接

1:连接成功,可通讯

2:正在关闭

3:连接已关闭或无法打开
*/

  //创建一个webSocket 实例
  var webSocket = new WebSocket("ws://192.168.31.152:8083");


  webSocket.onerror = function (event){
    onError(event);
  };

  // 打开websocket
  webSocket.onopen = function (event){
    onOpen(event);
  };

  //监听消息
  webSocket.onmessage = function (event){
    onMessage(event);
  };


  webSocket.onclose = function (event){
    onClose(event);
  }

  //关闭监听websocket
  function onError(event){
    document.getElementById("msg").innerHTML = "<p>close</p>";
    console.log("error"+event.data);
  };

  function onOpen(event){
    console.log("open:"+sockState());
    document.getElementById("msg").innerHTML = "<p>Connect to Service</p>";
  };
  function onMessage(event){
    console.log("onMessage");
    document.getElementById("msg").innerHTML += "<p>response:"+event.data+"</p>"
  };

  function onClose(event){
    document.getElementById("msg").innerHTML = "<p>close</p>";
    console.log("close:"+sockState());
    webSocket.close();
  }

  function sockState(){
    var status = ['未连接','连接成功,可通讯','正在关闭','连接已关闭或无法打开'];
      return status[webSocket.readyState];
  }


 function start(event){
    console.log(webSocket);
    var msg = document.getElementById('text').value;
    document.getElementById('text').value = '';
    console.log("send:"+sockState());
    console.log("msg="+msg);
    webSocket.send("msg="+msg);
    document.getElementById("msg").innerHTML += "<p>request"+msg+"</p>"
  };

  function close(event){
    webSocket.close();
  }
 </script>
 </body>
</html>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
用Socket发送电子邮件(利用需要验证的SMTP服务器)
Oct 09 PHP
Apache设置虚拟WEB
Oct 09 PHP
jQuery中的RadioButton,input,CheckBox取值赋值实现代码
Feb 18 PHP
培养自己的php编码规范
Sep 28 PHP
关于php中的json_encode()和json_decode()函数的一些说明
Nov 20 PHP
ajax调用返回php接口返回json数据的方法(必看篇)
May 05 PHP
laravel实现分页样式替换示例代码(增加首、尾页)
Sep 22 PHP
PHP实现动态添加XML中数据的方法
Mar 30 PHP
PHP实现的简单留言板功能示例【基于thinkPHP框架】
Dec 07 PHP
PHP获取访问设备信息的方法示例
Feb 20 PHP
php设计模式之策略模式实例分析【星际争霸游戏案例】
Mar 26 PHP
php设计模式之职责链模式实例分析【星际争霸游戏案例】
Mar 27 PHP
总结PHP内存释放以及垃圾回收
Mar 29 #PHP
PHP+Ajax实现的博客文章添加类别功能示例
Mar 29 #PHP
PHP使用文件锁解决高并发问题示例
Mar 29 #PHP
PHP实现微信支付(jsapi支付)流程步骤详解
Mar 15 #PHP
PHP实现的数组和XML文件相互转换功能示例
Mar 15 #PHP
PHP实现用户异地登录提醒功能的方法【基于thinkPHP框架】
Mar 15 #PHP
laravel框架关于搜索功能的实现
Mar 15 #PHP
You might like
把jquery 的dialog和ztree结合实现步骤
2013/08/02 Javascript
JS中把字符转成ASCII值的函数示例代码
2013/11/21 Javascript
jquery实现侧边弹出的垂直导航
2014/12/09 Javascript
jQuery中filter()方法用法实例
2015/01/06 Javascript
JavaScript显示表单内元素数量的方法
2015/04/02 Javascript
简单介绍JavaScript的变量和数据类型
2015/06/03 Javascript
简介JavaScript中的setHours()方法的使用
2015/06/11 Javascript
使用JS动态显示文本
2017/09/09 Javascript
详解Vue快速零配置的打包工具——parcel
2018/01/16 Javascript
node.js博客项目开发手记
2018/03/16 Javascript
vue组件name的作用小结
2018/05/23 Javascript
vue构建动态表单的方法示例
2018/09/22 Javascript
H5+C3+JS实现五子棋游戏(AI篇)
2020/05/28 Javascript
Node.js之readline模块的使用详解
2019/03/25 Javascript
发布订阅模式在vue中的实际运用实例详解
2019/06/09 Javascript
vue 导出文件,携带请求头token操作
2020/09/10 Javascript
Python获取linux主机ip的简单实现方法
2016/04/18 Python
Pandas Shift函数的基础入门学习笔记
2018/11/16 Python
Django接收照片储存文件的实例代码
2020/03/07 Python
小 200 行 Python 代码制作一个换脸程序
2020/05/12 Python
Python selenium模拟手动操作实现无人值守刷积分功能
2020/05/13 Python
解析Python 偏函数用法全方位实现
2020/06/26 Python
波兰在线儿童和婴儿用品零售商:pinkorblue
2019/06/29 全球购物
nohup的用法
2012/11/26 面试题
人事文员岗位职责
2014/02/16 职场文书
公司活动方案范文
2014/03/06 职场文书
一年级评语大全
2014/04/23 职场文书
计算机多媒体专业自荐信
2014/07/04 职场文书
2014年新农村建设工作总结
2014/12/01 职场文书
大学生自荐材料范文
2014/12/30 职场文书
成绩报告单家长评语
2014/12/30 职场文书
法律意见书范文
2015/05/20 职场文书
横空出世观后感
2015/06/09 职场文书
基于Redis的List实现特价商品列表功能
2021/08/30 Redis
Java 死锁解决方案
2022/05/11 Java/Android
Java代码规范与质量检测插件SonarLint的使用
2022/08/05 Java/Android