这里我们只以tcp服务举例,协议以换行符举例.我们先看最简单的单进程阻塞模型
首先一个socket服务的代码如下:
<?php /** * 单进程阻塞式--同时只能处理一个连接 */ class Xtgxiso_server { public $socket = false; public $onConnect = null; public $onMessage = null; public $onClose = null; function __construct($host="0.0.0.0",$port=1215) { $this->socket = stream_socket_server("tcp://".$host.":".$port,$errno, $errstr); if (!$this->socket) die($errstr."--".$errno); } public function run(){ while ( 1 ) { echo "waiting...\n"; $conn = stream_socket_accept($this->socket, -1); if ( !$conn ){ continue; } if($this->onConnect) { call_user_func($this->onConnect, $conn); } $receive = ''; $buffer = ''; while ( 1 ) { $buffer = fread($conn, 3); if($buffer === '' || $buffer === false) { if ( $this->onClose ){ call_user_func($this->onClose, $conn); } break; } $pos = strpos($buffer, "\n"); if($pos === false) { $receive .= $buffer; //echo "received:".$buffer.";not all package,continue recdiveing\n"; }else{ $receive .= trim(substr ($buffer,0,$pos+1)); $buffer = substr($buffer,$pos+1); if($this->onMessage) { call_user_func($this->onMessage, $conn, $receive); } switch ( $receive ){ case "quit": echo "client close conn\n"; fclose($conn); break 2; default: //echo "all package:\n"; //echo $receive."\n"; break; } $receive=''; } } } fclose($socket); } } $server = new Xtgxiso_server(); $server->onConnect = function($conn){ echo "onConnect -- accepted " . stream_socket_get_name($conn,true) . "\n"; fwrite($conn,"conn success\n"); }; $server->onMessage = function($conn,$msg){ echo "onMessage --" . $msg . "\n"; fwrite($conn,"received ".$msg."\n"); }; $server->onClose = function($conn){ echo "onClose --" . stream_socket_get_name($conn,true) . "\n"; fwrite($conn,"onClose "."\n"); }; $server->run();
大家可以用telnet命令来测试,这也是用换行符协议的原因,方便测试。可以很明显的看到,这个服务同时只能处理一个连接,肯定不会用人用这种方式来实现socket服务的