php+html5基于websocket实现聊天室的方法


Posted in PHP onJuly 17, 2015

本文实例讲述了php+html5基于websocket实现聊天室的方法。分享给大家供大家参考。具体如下:

html5的websocket 实现了双向通信,折腾了几天弄了个聊天室,分享给大家

<?php
error_reporting(E_ALL);
ob_implicit_flush();
$sk=new Sock('127.0.0.1',8000);
$sk->run();
class Sock{
 public $sockets;
 public $users;
 public $master;
 public function __construct($address, $port){
  $this->master=$this->WebSocket($address, $port);
  $this->sockets=array('s'=>$this->master);
 }
 function run(){
  while(true){
   $changes=$this->sockets;
   socket_select($changes,$write=NULL,$except=NULL,NULL);
   foreach($changes as $sock){
    if($sock==$this->master){
     $client=socket_accept($this->master);
     //$key=uniqid();
     $this->sockets[]=$client;
     $this->users[]=array(
      'socket'=>$client,
      'shou'=>false
     );
    }else{
     $len=socket_recv($sock,$buffer,2048,0);
     $k=$this->search($sock);
     if($len<7){
      $name=$this->users[$k]['ming'];
      $this->close($sock);
      $this->send2($name,$k);
      continue;
     }
     if(!$this->users[$k]['shou']){
      $this->woshou($k,$buffer);
     }else{
      $buffer = $this->uncode($buffer);
      $this->send($k,$buffer);
     }
    }
   }
  }
 }
 function close($sock){
  $k=array_search($sock, $this->sockets);
  socket_close($sock);
  unset($this->sockets[$k]);
  unset($this->users[$k]);
  $this->e("key:$k close");
 }
 function search($sock){
  foreach ($this->users as $k=>$v){
   if($sock==$v['socket'])
   return $k;
  }
  return false;
 }
 function WebSocket($address,$port){
  $server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
  socket_bind($server, $address, $port);
  socket_listen($server);
  $this->e('Server Started : '.date('Y-m-d H:i:s'));
  $this->e('Listening on : '.$address.' port '.$port);
  return $server;
 }
 function woshou($k,$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($this->users[$k]['socket'],$new_message,strlen($new_message));
  $this->users[$k]['shou']=true;
  return true;
 }
 function uncode($str){
  $mask = array(); 
  $data = ''; 
  $msg = unpack('H*',$str); 
  $head = substr($msg[1],0,2); 
  if (hexdec($head{1}) === 8) { 
   $data = false; 
  }else if (hexdec($head{1}) === 1){ 
   $mask[] = hexdec(substr($msg[1],4,2)); 
   $mask[] = hexdec(substr($msg[1],6,2)); 
   $mask[] = hexdec(substr($msg[1],8,2)); 
   $mask[] = hexdec(substr($msg[1],10,2)); 
   $s = 12; 
   $e = strlen($msg[1])-2; 
   $n = 0; 
   for ($i=$s; $i<= $e; $i+= 2) { 
    $data .= chr($mask[$n%4]^hexdec(substr($msg[1],$i,2)));
    $n++; 
   } 
  } 
  return $data;
 }
 function code($msg){
  $msg = preg_replace(array('/\r$/','/\n$/','/\r\n$/',), '', $msg);
  $frame = array(); 
  $frame[0] = '81'; 
  $len = strlen($msg); 
  $frame[1] = $len<16?'0'.dechex($len):dechex($len); 
  $frame[2] = $this->ord_hex($msg); 
  $data = implode('',$frame); 
  return pack("H*", $data); 
 }
 function ord_hex($data) { 
  $msg = ''; 
  $l = strlen($data); 
  for ($i= 0; $i<$l; $i++) { 
   $msg .= dechex(ord($data{$i})); 
  } 
  return $msg; 
 }
 function send($k,$msg){
  /*$this->send1($k,$this->code($msg),'all');*/
  parse_str($msg,$g);
  $this->e($msg);
  $ar=array();
  if($g['type']=='add'){
   $this->users[$k]['ming']=$g['ming'];
   $ar['add']=true;
   $ar['nrong']='欢迎'.$g['ming'].'加入!';
   $ar['users']=$this->getusers();
   $key='all';
  }else if($g['type']=='ltiao'){
   $ar['nrong']=$g['nr'];
   $key=$g['key'];
  }
  $msg=json_encode($ar);
  $this->e($msg);
  $msg = $this->code($msg);
  $this->send1($k,$msg,$key);
  //socket_write($this->users[$k]['socket'],$msg,strlen($msg));
 }
 function getusers(){
  $ar=array();
  foreach($this->users as $k=>$v){
   $ar[$k]=$v['ming'];
  }
  return $ar;
 }
 function send1($k,$str,$key='all'){
  if($key=='all'){
   foreach($this->users as $v){
    socket_write($v['socket'],$str,strlen($str));
   }
  }else{
   if($k!=$key)
   socket_write($this->users[$k]['socket'],$str,strlen($str));
   socket_write($this->users[$key]['socket'],$str,strlen($str));
  }
 }
 function send2($ming,$k){
  $ar['remove']=true;
  $ar['removekey']=$k;
  $ar['nrong']=$ming.'退出聊天室';
  $str = $this->code(json_encode($ar));
  $this->send1(false,$str,'all');
 }
 function e($str){
  $path=dirname(__FILE__).'/log.txt';
  $str=$str."\n";
  error_log($str,3,$path);
  echo iconv('utf-8','gbk//IGNORE',$str);
 }
}
?>

希望本文所述对大家的php程序设计有所帮助。

PHP 相关文章推荐
傻瓜化配置PHP环境――Appserv
Dec 13 PHP
PHP 函数语法介绍一
Jun 14 PHP
PHP Undefined index报错的修复方法
Jul 17 PHP
php实现的获取网站备案信息查询代码(360)
Sep 23 PHP
php实现memcache缓存示例讲解
Dec 04 PHP
php一行代码获取文件后缀名实例分析
Nov 12 PHP
windows下配置php5.5开发环境及开发扩展
Dec 25 PHP
thinkPHP模型初始化实例分析
Dec 03 PHP
php中html_entity_decode实现HTML实体转义
Jun 13 PHP
thinkPHP框架实现类似java过滤器的简单方法示例
Sep 05 PHP
tp5(thinkPHP5)框架实现多数据库查询的方法
Jan 10 PHP
ThinkPHP框架整合微信支付之Native 扫码支付模式一图文详解
Apr 09 PHP
php获取错误信息的方法
Jul 17 #PHP
PHP实现C#山寨ArrayList的方法
Jul 16 #PHP
PHP计算加权平均数的方法
Jul 16 #PHP
PHP基于工厂模式实现的计算器实例
Jul 16 #PHP
CodeIgniter与PHP5.6的兼容问题
Jul 16 #PHP
PHP实现上传文件并存进数据库的方法
Jul 16 #PHP
PHP实现通过get方式识别用户发送邮件的方法
Jul 16 #PHP
You might like
jQuery+PHP+ajax实现微博加载更多内容列表功能
2014/06/27 PHP
Yii2中datetime类的使用
2016/12/17 PHP
详解yii2使用多个数据库的案例
2017/06/16 PHP
jQuery 性能优化指南 (1)
2009/05/21 Javascript
js正则表达式的使用详解
2013/07/09 Javascript
Javascript的严格模式strict mode详细介绍
2014/06/06 Javascript
Node.js 制作实时多人游戏框架
2015/01/08 Javascript
使用jquery 简单实现下拉菜单
2015/01/14 Javascript
老生常谈 关于JavaScript的类的继承
2016/06/24 Javascript
Three.js快速入门教程
2016/09/09 Javascript
JS图片压缩(pc端和移动端都适用)
2017/01/12 Javascript
JS给按钮添加跳转功能类似a标签
2017/05/30 Javascript
详解vue+vuex+koa2开发环境搭建及示例开发
2018/01/22 Javascript
vue-cli中的babel配置文件.babelrc实例详解
2018/02/22 Javascript
JavaScript设计模式之装饰者模式实例详解
2019/01/17 Javascript
NodeJs操作MongoDB教程之分页功能以及常见问题
2019/04/09 NodeJs
关于Node.js中频繁修改代码重启服务器的问题
2020/10/15 Javascript
Python的Flask框架中实现分页功能的教程
2015/04/20 Python
详解Python list 与 NumPy.ndarry 切片之间的对比
2017/07/24 Python
python OpenCV学习笔记直方图反向投影的实现
2018/02/07 Python
Python给定一个句子倒序输出单词以及字母的方法
2018/12/20 Python
Python通过for循环理解迭代器和生成器实例详解
2019/02/16 Python
Python 窗体(tkinter)按钮 位置实例
2019/06/13 Python
Python collections中的双向队列deque简单介绍详解
2019/11/04 Python
基于python实现模拟数据结构模型
2020/06/12 Python
Python装饰器如何实现修复过程解析
2020/09/05 Python
Grid 宫格常用布局的实现
2020/01/10 HTML / CSS
HTML5之SVG 2D入门12—SVG DOM及DOM操作介绍
2013/01/30 HTML / CSS
PHP如何设置和取得Cookie值
2015/06/30 面试题
一些关于MySql加速和优化的面试题
2014/01/30 面试题
学前班教师的自我鉴定
2013/12/05 职场文书
有关环保的标语
2014/06/13 职场文书
中央空调节能方案
2014/06/15 职场文书
保护环境建议书作文300字
2015/09/14 职场文书
opencv读取视频并保存图像的方法
2021/06/04 Python
mysql 子查询的使用
2022/04/28 MySQL