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 相关文章推荐
桌面中心(三)修改数据库
Oct 09 PHP
MYSQL环境变量设置方法
Jan 15 PHP
php公用函数列表[正则]
Feb 22 PHP
学习使用curl采集curl使用方法
Jan 11 PHP
获取PHP警告错误信息的解决方法
Jun 03 PHP
PHP对象相互引用的内存溢出实例分析
Aug 28 PHP
php数组排序usort、uksort与sort函数用法
Nov 17 PHP
php多重接口的实现方法
Jun 20 PHP
PHP之将POST数据转化为字符串的实现代码
Nov 03 PHP
PHP实现websocket通信的方法示例
Aug 28 PHP
PHP高并发和大流量解决方案整理
Dec 24 PHP
让你的PHP,APACHE,NGINX支持大文件上传
Mar 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
PHP COOKIE及时生效的方法介绍
2014/02/14 PHP
php操作redis中的hash和zset类型数据的方法和代码例子
2014/07/05 PHP
thinkphp3.2中Lite文件替换框架入口文件或应用入口文件的方法
2015/05/21 PHP
php通过smtp邮件验证登陆的方法
2016/05/11 PHP
PHP身份证校验码计算方法
2016/08/10 PHP
thinkPHP+phpexcel实现excel报表输出功能示例
2017/06/06 PHP
JS获取IUSR_机器名和IWAM_机器名帐号的密码
2006/12/06 Javascript
JQuery获取浏览器窗口内容部分高度的代码
2012/02/24 Javascript
JQuery 图片的展开和伸缩实例讲解
2013/04/18 Javascript
图片动画横条广告带上下滚动的JS代码
2013/10/25 Javascript
JavaScript中全选、全不选、反选、无刷新删除、批量删除、即点即改入库(在yii框架中操作)的代码分享
2016/11/01 Javascript
深入理解Angularjs向指令传递数据双向绑定机制
2016/12/31 Javascript
详解JS中的立即执行函数
2017/02/24 Javascript
ES6新数据结构Set与WeakSet用法分析
2017/03/31 Javascript
JS+canvas动态绘制饼图的方法示例
2017/09/12 Javascript
微信小程序使用input组件实现密码框功能【附源码下载】
2017/12/11 Javascript
Angular动态绑定样式及改变UI框架样式的方法小结
2018/09/03 Javascript
python共享引用(多个变量引用)示例代码
2013/12/04 Python
Python实现计算两个时间之间相差天数的方法
2017/05/10 Python
Python多进程库multiprocessing中进程池Pool类的使用详解
2017/11/24 Python
使用EduBlock轻松学习Python编程
2018/10/08 Python
Python Django框架单元测试之文件上传测试示例
2019/05/17 Python
浅谈css3中的前缀
2016/07/20 HTML / CSS
银行实习自我鉴定
2013/10/12 职场文书
网络工程专业自荐信范文
2014/03/16 职场文书
珠宝店促销方案
2014/03/21 职场文书
项目经理聘任书
2014/03/29 职场文书
歌颂祖国演讲稿
2014/05/04 职场文书
2014医学院领导干部四风对照检查材料思想汇报
2014/09/16 职场文书
印刷技术专业自荐信
2014/09/18 职场文书
优秀教师个人总结
2015/02/11 职场文书
2015年新教师工作总结
2015/04/28 职场文书
预防艾滋病宣传活动总结
2015/05/09 职场文书
巾帼建功标兵先进事迹材料
2016/02/29 职场文书
将图片保存到mysql数据库并展示在前端页面的实现代码
2021/05/02 MySQL
Python3接口性能测试实例代码
2021/06/20 Python