(php) 如何用php实现websocket?

php-fpm能实现websocket吗?目前貌似还没看到这种实现,websocket貌似需要长连接,但php过一会就自己断掉了。我的理解正确吗?目前好像只有node.js,java等等这种常驻内存的服务端语言才能实现,php有可能实现吗?

php-fpm无法支持websocket协议。php也可以常驻内存,php版本的websocket server推荐用workerman,文档比较全,使用简单也非常稳定,也是常驻内存的,性能也比较高https://github.com/walkor/workerman

也可以用swoole.com, 是一个扩展,支持的特性多一些,使用起来也复杂一些,比较适合有点c基础的coder

PHP 可以通过 PHP CLI 常驻内存… http://www.cnblogs.com/hustskyking/p/websocket-with-php.html

php有可用的websocket库,不需要php-fpm。

目前比较成熟的有swoole(swoole.com),和workman(workman.net)

swoole是c写的php扩展。 效率比nodejs还要高
workman是纯php实现。

两者都号称可以实现并发百万TCP连接,我还没研究到这步。
目前我还只是将swoole用在了手游的在线同步战斗系统,过程比较顺利。

这个要通过cmd运行的 具体带的参数有点忘记了
<?php error_reportingE_ALL; set_time_limit0; ob_implicit_flush; //创建一个socket连接 设置参数 绑定 监听 并且返回 $master = WebSocket"localhost",12345; //标示是否已经进行过握手了 $is_shaked = false; //是否已经关闭 $is_closed = true; //将socket变为一个可用的socket whiletrue{ //如果是关闭状态并且是没有握手的话 则创建一个可用的socket(貌似第二个条件可以去除) if$is_closed && !$is_shaked{ if$sock = socket_accept$master < 0{ echo "socket_accept failed: reason: " . socket_strerror$sock . "
"; } //将关闭状态修改为false $is_closed = false; } //开始进行数据处理 process$sock; } //处理请求的函数 function process$socket{ //先从获取到全局变量 global $is_closed, $is_shaked; //从socket中获取数据 $buffer = socket_read$socket,2048; //如果buffer返回值为false并且已经握手的话 则断开连接 if!$buffer && $is_shaked{ disconnect$socket; }else{ //如果没有握手的话则握手 并且修改握手状态 if$is_shaked == false{ $return_str = dohandshake$buffer; $is_shaked = true; }else{ //如果已经握手的话则送入deal函数中进行相应处理 $data_str = decode$buffer; //解析出来的从前端送来的内容 console$data_str; $return_str = encodedeal$socket, $data_str; //$return_str = encode$data_str; } //将应该返回的字符串写入socket返回 socket_write$socket,$return_str,strlen$return_str; } } function deal$socket, $msgObj{ $obj = json_decode$msgObj; foreach$obj as $key=>$value{ if$key == close{ disconnect$socket; consoleclose success; return close success; }else if$key == msg{ console$value."
"; return $value; } } } //获取头部信息 function getheaders$req{ $r=$h=$o=null; ifpreg_match"/GET .* HTTP/" ,$req,$match{ $r=$match[1]; } ifpreg_match"/Host: .* /" ,$req,$match{ $h=$match[1]; } ifpreg_match"/Origin: .* /",$req,$match{ $o=$match[1]; } ifpreg_match"/Sec-WebSocket-Key: .* /",$req,$match{ $key=$match[1]; } ifpreg_match"/ .*?$/",$req,$match{ $data=$match[1]; } return array$r,$h,$o,$key,$data; } function WebSocket$address,$port{ $master=socket_createAF_INET, SOCK_STREAM, SOL_TCP or die"socket_create failed"; socket_set_option$master, SOL_SOCKET, SO_REUSEADDR, 1 or die"socket_option failed"; socket_bind$master, $address, $port or die"socket_bind failed"; socket_listen$master,20 or die"socket_listen failed"; echo "Server Started : ".dateY-m-d H:i:s."
"; echo "Master socket : ".$master."
"; echo "Listening on : ".$address." port ".$port." "; return $master; } function dohandshake$buffer{ list$resource,$host,$origin,$key,$data = getheaders$buffer; echo "resource is $resource
"; echo "origin is $origin
"; echo "host is $host
"; echo "key is $key "; $response_key = base64_encodesha1$key.258EAFA5-E914-47DA-95CA-C5AB0DC85B11, true; $return_str = "HTTP/1.1 101 Switching Protocols ". "Upgrade: websocket ". "Connection: Upgrade ". "Sec-WebSocket-Accept: $response_key "; return $return_str; } function console$msg{ $msg = transToGBK$msg; echo "$msg
"; return $msg; } function decode$msg="" { $mask = array; $data = ""; $msg = unpack"H*",$msg; $head = substr$msg[1],0,2; if hexdec$head{1} === 8{ $data = false; } else if hexdec$head{1} === 1{ $mask[] = hexdecsubstr$msg[1],4,2; $mask[] = hexdecsubstr$msg[1],6,2; $mask[] = hexdecsubstr$msg[1],8,2; $mask[] = hexdecsubstr$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]^hexdecsubstr$msg[1],$i,2; $n++; } } return $data; } function encode$msg=""{ $frame = array; $frame[0] = "81"; $msg .= is ok; $len = strlen$msg; $frame[1] = $len<16?"0".dechex$len:dechex$len; $frame[2] = ord_hex$msg; $data = implode"",$frame; return pack"H*", $data; } function transToGBK$s{//UTF8->GBK //echo $s; return iconv"UTF-8", "GBK", $s; return $s; } function ord_hex$data{ $msg = ""; $l = strlen$data; for $i=0; $i<$l; $i++{ //ord是返回字符串第一个字符的ascii值 //dechex把十进制转换为十六进制 $msg .= dechexord$data{$i}; } return $msg; } function disconnect$socket{ global $is_shaked, $is_closed; $is_shaked = false; $is_closed = true; socket_close$socket; }
?>

发表评论

电子邮件地址不会被公开。 必填项已用*标注