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代码
Mar 08 PHP
PHP详细彻底学习Smarty
Mar 27 PHP
PHP中的strtr函数使用介绍(str_replace)
Oct 20 PHP
PHP高级对象构建 多个构造函数的使用
Feb 05 PHP
phpize的深入理解
Jun 03 PHP
php修改NetBeans默认字体的大小
Jul 02 PHP
php实现excel中rank函数功能的方法
Jan 20 PHP
PHP实用函数分享之去除多余的0
Feb 06 PHP
php计算两个整数的最大公约数常用算法小结
Mar 05 PHP
php实现XML和数组的相互转化功能示例
Feb 08 PHP
支持汉转拼和拼音分词的PHP中文工具类ChineseUtil
Feb 23 PHP
laravel 5.3 单用户登录简单实现方法
Oct 14 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 array_intersect比array_diff快(附详细的使用说明)
2011/07/03 PHP
基于python发送邮件的乱码问题的解决办法
2013/04/25 PHP
PHP中的随机性 你觉得自己幸运吗?
2016/01/22 PHP
详解PHP中websocket的使用方法
2016/09/15 PHP
PHP针对中英文混合字符串长度判断及截取方法示例
2017/03/31 PHP
Laravel中的chunk组块结果集处理与注意问题
2018/08/15 PHP
JQuery中关于jquery.js与jquery.min.js的比较探讨
2013/05/15 Javascript
javascript自定义的addClass()方法
2014/05/28 Javascript
js中iframe调用父页面的方法
2014/10/30 Javascript
使用javascript获取页面名称
2014/12/23 Javascript
jquery中JSON的解析方式
2015/03/16 Javascript
JS实现的数组全排列输出算法
2015/03/19 Javascript
jQuery mobile 移动web(6)
2015/12/20 Javascript
运用js教你轻松制作html音乐播放器
2020/04/17 Javascript
Javascript仿京东放大镜的效果
2017/03/01 Javascript
nodejs对express中next函数的一些理解
2017/09/08 NodeJs
Vue实现点击后文字变色切换方法
2018/02/11 Javascript
vue.js实现格式化时间并每秒更新显示功能示例
2018/07/07 Javascript
微信小程序清空输入框信息与实现屏幕往上滚动的示例代码
2020/06/23 Javascript
python自动化测试之setUp与tearDown实例
2014/09/28 Python
Python SQLAlchemy入门教程(基本用法)
2019/11/11 Python
Python使用pymysql模块操作mysql增删改查实例分析
2019/12/19 Python
Python发送手机动态验证码代码实例
2020/02/28 Python
澳大利亚药房在线:ThePharmacy
2017/10/04 全球购物
超级英雄、电影和电视、乐队和音乐T恤:Loud Clothing
2019/09/01 全球购物
初中考试作弊检讨书
2014/02/01 职场文书
小学教师国培感言
2014/02/08 职场文书
《月迹》教学反思
2014/02/19 职场文书
教师师德考核自我评价
2014/09/13 职场文书
房产协议书范本
2014/10/18 职场文书
2014年教学工作总结
2014/11/13 职场文书
环保主题班会教案
2015/08/13 职场文书
小学班主任研修日志
2015/11/13 职场文书
小学英语教学反思范文
2016/02/15 职场文书
高中语文教学反思范文
2016/02/16 职场文书
Go语言测试库testify使用学习
2022/07/23 Golang