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 stream_context_create()作用和用法分析
Mar 29 PHP
php max_execution_time执行时间问题
Jul 17 PHP
关于PHP session 存储方式的详细介绍
Jun 25 PHP
crontab无法执行php的解决方法
Jan 25 PHP
微信支付开发发货通知实例
Jul 12 PHP
PHP 中使用ajax时一些常见错误总结整理
Feb 27 PHP
Yii2 如何在modules中添加验证码的方法
Jun 19 PHP
PHP清除缓存的几种方法总结
Sep 12 PHP
PHP延迟静态绑定的深入讲解
Apr 02 PHP
PHP PDOStatement::rowCount讲解
Feb 01 PHP
PHP实现的用户注册表单验证功能简单示例
Feb 25 PHP
laravel框架查询数据集转为数组的两种方法
Oct 10 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 Curl出现403错误的解决办法
2014/05/29 PHP
PHP中读取文件的8种方法和代码实例
2014/08/05 PHP
php基本函数汇总
2015/07/09 PHP
php根据用户语言跳转相应网页
2015/11/04 PHP
jquery text,radio,checkbox,select操作实现代码
2009/07/09 Javascript
js DOM模型操作
2009/12/28 Javascript
利用location.hash实现跨域iframe自适应
2010/05/04 Javascript
js计算字符串长度包含的中文是utf8格式
2013/10/15 Javascript
js 实现菜单左右滚动显示示例介绍
2013/11/21 Javascript
7个有用的jQuery代码片段分享
2015/05/19 Javascript
js判断radiobuttonlist的选中值显示/隐藏其它模块的实现方法
2016/08/25 Javascript
AngularJs IE Compatibility 兼容老版本IE
2016/09/01 Javascript
关于两个jQuery(js)特效冲突的bug的解决办法
2016/09/04 Javascript
angular中实现控制器之间传递参数的方式
2017/04/24 Javascript
关于使用js算总价的问题
2017/06/23 Javascript
使用JS和canvas实现gif动图的停止和播放代码
2017/09/01 Javascript
如何重置vue打印变量的显示方式
2017/12/06 Javascript
Element实现表格分页数据选择+全选所有完善批量操作
2019/06/07 Javascript
VSCode搭建React Native环境
2020/05/07 Javascript
[08:08]2014DOTA2国际邀请赛中国区预选赛精彩TOPPLAY
2014/06/25 DOTA
python中文乱码的解决方法
2013/11/04 Python
python新手经常遇到的17个错误分析
2014/07/30 Python
Python通过调用mysql存储过程实现更新数据功能示例
2018/04/03 Python
Windows系统下PhantomJS的安装和基本用法
2018/10/21 Python
Python实现 版本号对比功能的实例代码
2019/04/18 Python
Django错误:TypeError at / 'bool' object is not callable解决
2019/08/16 Python
Kears+Opencv实现简单人脸识别
2019/08/28 Python
python生成器用法实例详解
2019/11/22 Python
Django单元测试中Fixtures用法详解
2020/02/25 Python
jenkins+python自动化测试持续集成教程
2020/05/12 Python
python和JavaScript哪个容易上手
2020/06/23 Python
英国的潮牌鞋履服饰商店:size?
2019/03/26 全球购物
Watch Station官方网站:世界一流的手表和智能手表
2020/01/05 全球购物
幼儿教师辞职信范文
2015/03/02 职场文书
html输入两个数实现加减乘除功能
2021/07/01 HTML / CSS
MySQL中EXPLAIN语句及用法
2022/05/20 MySQL