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制作静态网站的模板框架
Oct 09 PHP
基于PHP CURL获取邮箱地址的详解
Jun 03 PHP
PHP学习笔记(一) 简单了解PHP
Aug 04 PHP
PHP中使用break跳出多重循环代码实例
Jan 21 PHP
PHP的Yii框架使用中的一些错误解决方法与建议
Aug 21 PHP
php基于单例模式封装mysql类完整实例
Oct 18 PHP
PHP静态成员变量和非静态成员变量详解
Feb 14 PHP
PHP实现登陆并抓取微信列表中最新一组微信消息的方法
Jul 10 PHP
PHP数据库操作三:redis用法分析
Aug 16 PHP
详解PHP中的外观模式facade pattern
Feb 05 PHP
PHP通过GD库实现验证码功能示例
Feb 23 PHP
PHP如何通过带尾指针的链表实现'队列'
Oct 22 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 采集心得技巧
2009/05/15 PHP
PHP设计模式(六)桥连模式Bridge实例详解【结构型】
2020/05/02 PHP
jquery 学习之二 属性 文本与值(text,val)
2010/11/25 Javascript
当滚动条滚动到页面底部自动加载增加内容的js代码
2014/05/13 Javascript
详解JavaScript中数组和字符串的lastIndexOf()方法使用
2016/03/13 Javascript
全面解析Bootstrap中Carousel轮播的使用方法
2016/06/13 Javascript
原生js实现可拖动的登录框效果
2017/01/21 Javascript
原生JS仿QQ阅读点击展开、收起效果
2017/03/08 Javascript
jquery实现的table排序功能示例
2017/03/10 Javascript
es6+angular1.X+webpack 实现按路由功能打包项目的示例
2017/08/16 Javascript
JS实现的抛物线运动效果示例
2018/01/30 Javascript
Vue.js 十五分钟入门图文教程
2018/09/12 Javascript
javascript刷新父页面方法汇总详解
2019/10/10 Javascript
如何在selenium中使用js实现定位
2020/08/18 Javascript
ES11屡试不爽的新特性,你用上了几个
2020/10/21 Javascript
[01:11:28]DOTA2-DPC中国联赛定级赛 RNG vs Phoenix BO3第一场 1月8日
2021/03/11 DOTA
分析python服务器拒绝服务攻击代码
2014/01/16 Python
Python中的闭包详细介绍和实例
2014/11/21 Python
Python学习小技巧总结
2018/06/10 Python
解决Tensorflow使用pip安装后没有model目录的问题
2018/06/13 Python
Python可视化mhd格式和raw格式的医学图像并保存的方法
2019/01/24 Python
pytorch 更改预训练模型网络结构的方法
2019/08/19 Python
解决pycharm不能自动补全第三方库的函数和属性问题
2020/03/12 Python
Django分组聚合查询实例分享
2020/04/29 Python
AmazeUI中各种的导航式菜单与解决方法
2020/08/19 HTML / CSS
三月学雷锋活动总结
2014/06/26 职场文书
工地门卫岗位职责范本
2014/07/01 职场文书
2015入党自传格式范文
2015/06/26 职场文书
企业宣传稿范文
2015/07/23 职场文书
国庆节主题班会
2015/08/15 职场文书
护士工作心得体会
2016/01/25 职场文书
导游词之舟山普陀山
2019/11/06 职场文书
如何在centos上使用yum安装rabbitmq-server
2021/03/31 Servers
MySQL系列之九 mysql查询缓存及索引
2021/07/02 MySQL
使用Redis做预定库存缓存功能
2022/04/02 Redis
Spring Data JPA框架自定义Repository接口
2022/04/28 Java/Android