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 相关文章推荐
使用zend studio for eclipse不能激活代码提示功能的解决办法
Oct 11 PHP
初学CAKEPHP 基础教程
Nov 02 PHP
PHP设计模式 注册表模式
Feb 05 PHP
php对mongodb的扩展(初出茅庐)
Nov 11 PHP
PHP系统命令函数使用分析
Jul 05 PHP
PHP 快速排序算法详解
Nov 10 PHP
ThinkPHP中order()使用方法详解
Apr 19 PHP
PHP使用星号隐藏用户名,手机和邮箱的实现方法
Sep 22 PHP
PHP 极验验证码实例讲解
Sep 29 PHP
thinkPHP5实现的查询数据库并返回json数据实例
Oct 23 PHP
Ajax中的JSON格式与php传输过程全面解析
Nov 14 PHP
PHP pthreads v3在centos7平台下的安装与配置操作方法
Feb 21 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利用APC模块实现文件上传进度条的方法
2015/01/26 PHP
php判断电子邮件是否正确方法
2018/12/04 PHP
做网页的一些技巧(续)
2007/02/01 Javascript
Sample script that displays all of the users in a given SQL Server DB
2007/06/16 Javascript
jquery.form.js实现将form提交转为ajax方式提交的方法
2015/04/07 Javascript
AngularJS中处理多个promise的方式
2016/02/02 Javascript
jQuery自定义插件详解及实例代码
2016/12/29 Javascript
详解angular2采用自定义指令(Directive)方式加载jquery插件
2017/02/09 Javascript
微信小程序之页面跳转和参数传递的实现
2017/09/29 Javascript
vue2.0使用swiper组件实现轮播效果
2017/11/27 Javascript
js原生方法被覆盖,从新赋值原生的方法
2018/01/02 Javascript
浅析Angular19 自定义表单控件
2018/01/31 Javascript
node获取客户端ip功能简单示例
2019/08/24 Javascript
基于JS实现简单滑块拼图游戏
2019/10/12 Javascript
Weex开发之WEEX-EROS开发踩坑(小结)
2019/10/16 Javascript
react quill中图片上传由默认转成base64改成上传到服务器的方法
2019/10/30 Javascript
Javascript异步执行不按顺序解决方案
2020/04/30 Javascript
[37:45]完美世界DOTA2联赛PWL S3 LBZS vs Phoenix 第二场 12.09
2020/12/11 DOTA
[06:59]DOTA2-DPC中国联赛3月7日Recap集锦
2021/03/11 DOTA
python解析html开发库pyquery使用方法
2014/02/07 Python
python画出三角形外接圆和内切圆的方法
2018/01/25 Python
django传值给模板, 再用JS接收并进行操作的实例
2018/05/28 Python
在Pycharm中设置默认自动换行的方法
2019/01/16 Python
Python代码太长换行的实现
2019/07/05 Python
Python 使用 PyMysql、DBUtils 创建连接池提升性能
2019/08/14 Python
详解查看Python解释器路径的两种方式
2020/10/15 Python
Python爬虫Scrapy框架CrawlSpider原理及使用案例
2020/11/20 Python
Python之字符串的遍历的4种方式
2020/12/08 Python
销售业务实习自我鉴定
2013/09/23 职场文书
高一新生军训方案
2014/05/12 职场文书
分公司任命书
2014/06/06 职场文书
股指期货心得体会
2014/09/13 职场文书
债务纠纷起诉书
2015/05/20 职场文书
情人节单身感言
2015/08/03 职场文书
清洁工工作总结
2015/08/11 职场文书
公文写作:新员工转正申请书范本3篇!
2019/08/07 职场文书