php soecket服务器搭建_使用php创建WebSocket服务

执行方法:

首先先修改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);

}

?>

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

$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));

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值