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的库,结果发现很多东西
Dec 31 PHP
php的urlencode()URL编码函数浅析
Aug 09 PHP
PHP 无限分类三种方式 非函数的递归调用!
Aug 26 PHP
PHP常用技巧总结(附函数代码)
Feb 04 PHP
PHP设计模式之装饰者模式
Feb 29 PHP
基于php实现长连接的方法与注意事项的问题
May 10 PHP
PHP连接Access数据库的方法小结
Jun 20 PHP
PHP的foreach中使用引用时需要注意的一个问题和解决方法
May 29 PHP
destoon文章模块调用企业会员资料的方法
Aug 22 PHP
PHP自动重命名文件实现方法
Nov 04 PHP
Yii2 输出xml格式数据的方法
May 03 PHP
PHP中new static()与new self()的比较
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
php中截取字符串支持utf-8
2007/01/18 PHP
PHP基础学习之流程控制的实现分析
2013/04/28 PHP
基于PHP实现发微博动态代码实例
2020/12/11 PHP
JavaScript window.setTimeout() 的详细用法
2009/11/04 Javascript
JavaScript控制Session操作方法
2013/01/17 Javascript
jquery中获取元素里某一特定子元素的代码
2014/12/02 Javascript
javascript实现网站加入收藏功能
2015/12/16 Javascript
jQuery+JSON实现AJAX二级联动实例分析
2015/12/18 Javascript
jQuery取得iframe中元素的常用方法详解
2016/01/14 Javascript
利用n工具轻松管理Node.js的版本
2017/04/21 Javascript
浅谈Node异步编程的机制
2017/10/18 Javascript
layui table 参数设置方法
2018/08/14 Javascript
Nuxt升级2.0.0时出现的问题(小结)
2018/10/08 Javascript
Vue中Table组件Select的勾选和取消勾选事件详解
2019/03/19 Javascript
p5.js临摹动态图形的方法
2019/10/23 Javascript
javascript实现的图片预览和上传功能示例【兼容IE 9】
2020/05/01 Javascript
[01:08:48]LGD vs OG 2018国际邀请赛淘汰赛BO3 第三场 8.25
2018/08/29 DOTA
python实现的防DDoS脚本
2011/02/08 Python
Python通过PIL获取图片主要颜色并和颜色库进行对比的方法
2015/03/19 Python
python利用paramiko连接远程服务器执行命令的方法
2017/10/16 Python
10分钟教你用Python实现微信自动回复功能
2018/11/28 Python
Python实现统计英文文章词频的方法分析
2019/01/28 Python
使用Python正则表达式操作文本数据的方法
2019/05/14 Python
Python多线程多进程实例对比解析
2020/03/12 Python
python3实现将json对象存入Redis以及数据的导入导出
2020/07/16 Python
StubHub德国:购买和出售门票
2017/09/06 全球购物
Osklen官方在线商店:巴西服装品牌
2019/04/25 全球购物
size?法国官网:英国伦敦的球鞋精品店
2020/03/15 全球购物
技术人员面试提纲
2013/11/28 职场文书
骨干教师培训制度
2014/01/13 职场文书
春节超市活动方案
2014/08/14 职场文书
集体生日活动方案
2014/08/18 职场文书
关于运动会的宣传稿
2015/07/23 职场文书
优秀共产党员主要事迹材料
2015/11/05 职场文书
Vue Element UI自定义描述列表组件
2021/05/18 Vue.js
mysql全面解析json/数组
2022/07/07 MySQL