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 相关文章推荐
跟我学小偷程序之成功偷取首页(第三天)
Oct 09 PHP
fleaphp crud操作之findByField函数的使用方法
Apr 23 PHP
新浪微博API开发简介之用户授权(PHP基础篇)
Sep 25 PHP
解析curl提交GET,POST,Cookie的简单方法
Jun 29 PHP
兼容ie6浏览器的php下载文件代码分享
Jul 14 PHP
PHP将HTML转换成文本的实现代码
Jan 21 PHP
详解PHP对象的串行化与反串行化
Jan 24 PHP
PHP中静态变量的使用方法实例分析
Dec 01 PHP
Zend Framework入门教程之Zend_Session会话操作详解
Dec 08 PHP
Yii2数据库操作常用方法小结
May 04 PHP
TP(thinkPHP)框架多层控制器和多级控制器的使用示例
Jun 13 PHP
详解提高使用Java反射的效率方法
Apr 29 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
php getsiteurl()函数
2009/09/05 PHP
php实现的遍历文件夹下所有文件,编辑删除
2010/01/05 PHP
php使用qr生成二维码的示例分享
2014/01/20 PHP
php判断电脑访问、手机访问的例子
2014/05/10 PHP
php面向对象的用户登录身份验证
2017/06/08 PHP
PHP安全之register_globals的on和off的区别
2020/07/23 PHP
JS与框架页的操作代码
2010/01/17 Javascript
aspx中利用js实现确认删除代码
2010/07/22 Javascript
判断输入是否为空,获得输入类型的JS代码
2013/10/30 Javascript
jquery实现网页查找功能示例分享
2014/02/12 Javascript
jQuery实现单击按钮遮罩弹出对话框(仿天猫的删除对话框)
2014/04/10 Javascript
学习javascript面向对象 javascript实现继承的方式
2016/01/04 Javascript
浅谈ElementUI中switch回调函数change的参数问题
2018/08/24 Javascript
详解Vue项目中出现Loading chunk {n} failed问题的解决方法
2018/09/14 Javascript
node中IO以及定时器优先级详解
2019/05/10 Javascript
js找出5个数中最大的一个数和倒数第二大的数实现方法示例小结
2020/03/04 Javascript
详解element-ui动态限定的日期范围选择器代码片段
2020/07/03 Javascript
[04:37]DOTA2英雄梦之声Vol20发条
2014/06/20 DOTA
python服务器端收发请求的实现代码
2014/09/29 Python
详谈Numpy中数组重塑、合并与拆分方法
2018/04/17 Python
Python简直是万能的,这5大主要用途你一定要知道!(推荐)
2019/04/03 Python
python3爬虫学习之数据存储txt的案例详解
2019/04/24 Python
Python sorted排序方法如何实现
2020/03/31 Python
详解CSS3的opacity属性设置透明效果的用法
2016/05/09 HTML / CSS
Html5新标签解释及用法
2012/02/17 HTML / CSS
html5 利用canvas实现超级玛丽简单动画
2013/09/06 HTML / CSS
Origins悦木之源英国官网:雅诗兰黛集团高端植物护肤品牌
2017/11/06 全球购物
捷克时尚网上商店:OTTO
2018/03/15 全球购物
拥有超过850家商店的美国在线派对商店:Party City
2018/10/21 全球购物
管理专员自荐信
2014/01/26 职场文书
人民教师的自我评价分享
2014/02/21 职场文书
求职信内容怎么写
2014/05/26 职场文书
大学国际贸易专业自荐信
2014/06/05 职场文书
2015年七夕爱情寄语
2015/03/24 职场文书
python多线程方法详解
2022/01/18 Python
教你win10系统中APPCRASH事件问题解决方法
2022/07/15 数码科技