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 相关文章推荐
56.com视频采集接口程序(PHP)
Sep 22 PHP
smarty模板局部缓存方法使用示例
Jun 17 PHP
PHP+jQuery 注册模块的改进(三):更新到Smarty3.1
Oct 14 PHP
php中的观察者模式简单实例
Jan 20 PHP
Java和PHP在Web开发方面对比分析
Mar 01 PHP
mod_php、FastCGI、PHP-FPM等PHP运行方式对比
Jul 02 PHP
php中10个不同等级压缩优化图片操作示例
Nov 14 PHP
postman的安装与使用方法(模拟Get和Post请求)
Aug 06 PHP
php 将json格式数据转换成数组的方法
Aug 21 PHP
PHP将整数数字转换为罗马数字实例分享
Mar 17 PHP
Laravel 添加多语言提示信息的方法
Sep 29 PHP
laravel实现上传图片的两种方式小结
Oct 12 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错误日志 display_errors与log_errors的区别
2012/10/09 PHP
Zend的MVC机制使用分析(一)
2013/05/02 PHP
一个简洁的PHP可逆加密函数(分享)
2013/06/06 PHP
php文字水印和php图片水印实现代码(二种加水印方法)
2013/12/25 PHP
php多维数组去掉重复值示例分享
2014/03/02 PHP
js focus不起作用的解决方法(主要是因为dom元素是否加载完成)
2010/11/05 Javascript
基于JavaScript实现定时跳转到指定页面
2016/01/01 Javascript
基于jQuery实现仿百度首页选项卡切换效果
2016/05/29 Javascript
JS拉起或下载app的实现代码
2017/02/22 Javascript
为你的微信小程序体积瘦身详解
2017/05/20 Javascript
jQuery实现简单的下拉菜单导航功能示例
2017/12/07 jQuery
微信小程序实现搜索功能并跳转搜索结果页面
2019/05/18 Javascript
vue+elementUI实现表格关键字筛选高亮
2020/10/26 Javascript
Javascript异步执行不按顺序解决方案
2020/04/30 Javascript
[01:20]DOTA2 2017国际邀请赛冠军之路无止竞
2017/06/19 DOTA
python启动办公软件进程(word、excel、ppt、以及wps的et、wps、wpp)
2009/04/09 Python
python 获取本机ip地址的两个方法
2013/02/25 Python
Python实现利用最大公约数求三个正整数的最小公倍数示例
2017/09/30 Python
python3中获取文件当前绝对路径的两种方法
2018/04/26 Python
python matplotlib 在指定的两个点之间连线方法
2018/05/25 Python
python用户评论标签匹配的解决方法
2018/05/31 Python
python自动化测试之DDT数据驱动的实现代码
2019/07/23 Python
Django app配置多个数据库代码实例
2019/12/17 Python
Python for循环通过序列索引迭代过程解析
2020/02/07 Python
基于python实现对文件进行切分行
2020/04/26 Python
Python中猜拳游戏与猜筛子游戏的实现方法
2020/09/04 Python
html5 canvas绘制矩形和圆形的实例代码
2016/06/16 HTML / CSS
美国最大的农村生活方式零售店:Tractor Supply Company(TSC)
2017/05/15 全球购物
法国大使拉杆箱官网:DELSEY Paris
2018/03/20 全球购物
Perfume’s Club中文官网:西班牙美妆在线零售品牌
2020/08/24 全球购物
英语专业自荐书
2014/06/13 职场文书
2014年学生会个人工作总结
2014/11/07 职场文书
前台接待岗位职责
2015/02/03 职场文书
工厂门卫岗位职责
2015/04/13 职场文书
祝福语集锦:送给毕业同学祝福语
2019/11/21 职场文书
MySQL的表级锁,行级锁,排它锁和共享锁
2022/07/15 MySQL