执行方法:
首先先修改server.php与index.html的ip
通过命令行执行 [php路径]php.exe "[文件路径]server.php"
然后通过浏览器打开index.html

<?
include 'websocket.class.php'; $config=array(
'address'=>'192.168.0.200',
'port'=>'8000',
'event'=>'WSevent',//回调函数的函数名
'log'=>true,
);
$websocket = new websocket($config);
$websocket->run();
function WSevent($type,$event){
global $websocket;
if('in'==$type){
$websocket->log('客户进入id:'.$event['k']);
}elseif('out'==$type){
$websocket->log('客户退出id:'.$event['k']);
}elseif('msg'==$type){
$websocket->log($event['k'].'消息:'.$event['msg']);
roboot($event['sign'],$event['msg']);
}
} function roboot($sign,$t){
global $websocket;
switch ($t)
{
case 'hello':
$show='hello,GIt @ OSC';
break;
case 'name':
$show='Robot';
break;
case 'time':
$show='当前时间:'.date('Y-m-d H:i:s');
break;
case '再见':
$show='( ^_^ )/~~拜拜';
$websocket->write($sign,'Robot:'.$show);
$websocket->close($sign);
return;
break;
case '天王盖地虎':
$array = array('小鸡炖蘑菇','宝塔震河妖','粒粒皆辛苦');
$show = $array[rand(0,2)];
break;
default:
$show='( ⊙o⊙?)不懂,你可以尝试说:hello,name,time,再见,天王盖地虎.';
}
$websocket->write($sign,'Robot:'.$show);
}
?>
<?php

class websocket{
public $log;
public $event;
public $signets;
public $users;
public $master;
public function __construct($config){
if (substr(php_sapi_name(), 0, 3) !== 'cli') {
die("请通过命令行模式运行!");
}
error_reporting(E_ALL);
set_time_limit(0);
ob_implicit_flush();
$this->event = $config['event'];
$this->log = $config['log'];
$this->master=$this->WebSocket($config['address'], $config['port']);
$this->sockets=array('s'=>$this->master);
}
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->log('开始监听: '.$address.' : '.$port);
return $server;
}
function run(){
while(true){
$changes=$this->sockets;
@socket_select($changes,$write=NULL,$except=NULL,NULL);
foreach($changes as $sign){
if($sign==$this->master){
$client=socket_accept($this->master);
$this->sockets[]=$client;
$user = array(
'socket'=>$client,
'hand'=>false,
);
$this->users[] = $user;
$k=$this->search($client);
$eventreturn = array('k'=>$k,'sign'=>$sign);
$this->eventoutput('in',$eventreturn);
}else{
$len=socket_recv($sign,$buffer,2048,0);
$k=$this->search($sign);
$user=$this->users[$k];
if($len<7){
$this->close($sign);
$eventreturn = array('k'=>$k,'sign'=>$sign);
$this->eventoutput('out',$eventreturn);
continue;
}
if(!$this->users[$k]['hand']){//没有握手进行握手
$this->handshake($k,$buffer);
}else{
$buffer = $this->uncode($buffer);
$eventreturn = array('k'=>$k,'sign'=>$sign,'msg'=>$buffer);
$this->eventoutput('msg',$eventreturn);
}
}
}
}
}
function search($sign){//通过标示遍历获取id
foreach ($this->users as $k=>$v){
if($sign==$v['socket'])
return $k;
}
return false;
}
function close($sign){//通过标示断开连接
$k=array_search($sign, $this->sockets);
socket_close($sign);
unset($this->sockets[$k]);
unset($this->users[$k]);
}
function handshake($k,$buffer){
$buf = substr($buffer,strpos($buffer,'Sec-WebSocket-Key:')+18);
$key = trim(substr($buf,0,strpos($buf,"rn")));
$new_key = base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true));
$new_message ="HTTP/1.1 101 Switching Protocolsrn";
$new_message .="Upgrade: websocketrn";
$new_message .="Sec-WebSocket-Version: 13rn";
$new_message .="Connection: Upgradern";
$new_message .="Sec-WebSocket-Accept:". $new_key ."rnrn";
socket_write($this->users[$k]['socket'],$new_message,strlen($new_message));
$this->users[$k]['hand']=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$/','/rn$/',), '', $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 idwrite($id,$t){//通过id推送信息
if(!$this->users[$id]['socket']){return false;}//没有这个标示
$t=$this->code($t);
return socket_write($this->users[$id]['socket'],$t,strlen($t));
}
function write($k,$t){//通过标示推送信息
$t=$this->code($t);
return socket_write($k,$t,strlen($t));
}
function eventoutput($type,$event){//事件回调
call_user_func($this->event,$type,$event);
}
function log($t){//控制台输出
if($this->log){
$t=$t."rn";
fwrite(STDOUT, iconv('utf-8','gbk//IGNORE',$t));
}
}
}

最新文章

  1. Deep Learning 23:dropout理解_之读论文“Improving neural networks by preventing co-adaptation of feature detectors”
  2. spring mvc 配置文件信息记录
  3. [vsftp]500 OOPS: cannot change directory
  4. 关于Action中ValidateXXX方法校验一次失败后\导致以后一直返回input视图的情况
  5. PHP 5.6启动失败failed to open configuration file &#39;/usr/local/php/etc/php-fpm.conf&#39;
  6. 对象-关系映射ORM(Object Relational Mapping)(转)
  7. HTML DOM 创建与修改
  8. 关于Linux路由表的route命令(转)
  9. SQL Server 移动数据库
  10. Memcached源码分析之从SET命令开始说起
  11. DailyTick 开发实录 —— UI 设计
  12. 拆开Ceph看队列和线程
  13. PLSQL程序流程
  14. JavaWeb学习笔记——jquery中的dom操作
  15. 影响 MySQL Server 性能的相关因素
  16. web前端页面设计小笔记
  17. laravel中及其常用的一些函数方法(自己看)和技巧(不断添加中)
  18. Spring的applicationContext.xml的疑问解析
  19. 从官网下载指定版本的JDK
  20. 10-free-must-read-books-machine-learning-data-science

热门文章

  1. Vmware(vmdk)虚拟机到hyperv(vhd)虚拟机转换
  2. java 执行redis的部分方法
  3. &lt;hdu - 1272&gt; 小希的迷宫 并查集问题 (注意特殊情况)
  4. POI插件使用读取office文件
  5. 【转】python删除文件里包含关键词的行
  6. X11 五子棋
  7. 解决Mac Linux USB Loader“Couldn&#39;t get security scoped bookmarks”错误
  8. kindeditor编辑器上传图片失败 错误 405.0解决办法(亲测)
  9. Font-Awesome IIS下不显示问题
  10. 关于jQuery表单校验