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 split汉字
Jun 05 PHP
php将数据库导出成excel的方法
May 07 PHP
ThinkPHP模板判断输出Defined标签用法详解
Jun 30 PHP
YII中assets的使用示例
Jul 31 PHP
php实现比较全的数据库操作类
Jun 18 PHP
PHP和Mysql中转UTF8编码问题汇总
Oct 10 PHP
thinkphp如何获取客户端IP
Nov 03 PHP
详解WordPress中分类函数wp_list_categories的使用
Jan 04 PHP
PHP 匿名函数与注意事项详细介绍
Nov 26 PHP
PHP实现的AES双向加密解密功能示例【128位】
Sep 03 PHP
PHP命名空间(namespace)原理与用法详解
Dec 11 PHP
Laravel相关的一些故障解决
Aug 19 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
使用PHPMyAdmin修复论坛数据库的图文方法
2012/01/09 PHP
谈谈PHP中substr和substring的正确用法及相关参数的介绍
2015/12/16 PHP
php使用正则表达式去掉html中的注释方法
2016/11/03 PHP
音乐播放用的的几个函数
2006/09/07 Javascript
js验证表单第二部分
2006/11/25 Javascript
jQuery动态显示和隐藏datagrid中的某一列的方法
2013/12/11 Javascript
kindeditor修复会替换script内容的问题
2015/04/03 Javascript
javascript实现检验的各种规则
2015/07/31 Javascript
基于html5和nodejs相结合实现websocket即使通讯
2015/11/19 NodeJs
React.js入门实例教程之创建hello world 的5种方式
2016/05/11 Javascript
jQuery+Ajax+PHP弹出层异步登录效果(附源码下载)
2016/05/27 Javascript
Angular.js之作用域scope'@','=','&amp;'实例详解
2017/02/28 Javascript
angular.js中解决跨域问题的三种方式
2017/07/12 Javascript
Bootstrap栅格系统的使用详解
2017/10/30 Javascript
新手快速上手webpack4打包工具的使用详解
2019/01/28 Javascript
记录一次开发微信网页分享的步骤
2019/05/07 Javascript
JavaScript实现的弹出遮罩层特效经典示例【基于jQuery】
2019/07/10 jQuery
vue3自定义dialog、modal组件的方法
2021/01/04 Vue.js
绘制微信小程序验证码功能的实例代码
2021/01/05 Javascript
Python入门篇之面向对象
2014/10/20 Python
详细讲解Python中的文件I/O操作
2015/05/24 Python
Python SqlAlchemy动态添加数据表字段实例解析
2018/02/07 Python
10个Python小技巧你值得拥有
2018/09/29 Python
django使用django-apscheduler 实现定时任务的例子
2019/07/20 Python
Python面向对象封装操作案例详解
2019/12/31 Python
Python Django2 model 查询介绍(条件、范围、模糊查询)
2020/03/16 Python
超全Python图像处理讲解(多模块实现)
2020/04/13 Python
使用keras内置的模型进行图片预测实例
2020/06/17 Python
HTML5+CSS3模仿优酷视频截图功能示例
2017/01/05 HTML / CSS
澳大利亚床上用品、浴巾和家居用品购物网站:Bambury
2020/04/16 全球购物
澳洲最大的时尚奢侈品电商平台:Cettire
2020/06/15 全球购物
物流仓管员工作职责
2014/01/06 职场文书
实践单位评语
2014/04/26 职场文书
党建工作整改措施
2014/10/28 职场文书
校本课程教学计划
2015/01/19 职场文书
建国70周年的心得体会(2篇)
2019/09/20 职场文书