这里我们只以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服务的
