php非阻塞服务器
<?php class PHPSocketServer
{
const ERROR = 0;
const LOG = 1;
const DEBUG = 2; private $aConfig = NULL;
private $hSocket = NULL;
private $aClients = array();
private $iRunning = 0;
private $iStartTime = 0;
private $iLastActivity = 0; private static $aDefaults = array
(
'main' => array
(
'address' => 'localhost',
'port' => 15151,
'backlog' => 200,
'select_timeout' => 1,
'pid_file' => 'phpserver.pid'
), 'verbosity' => array
(
'echo_log' => 1,
'echo_debug' => 0,
'echo_errors' => 1,
'log_errors' => 1
)
); public function getPidFile()
{
return $this->aConfig['main']['pid_file'];
} private static function getName( $hSocket )
{
return socket_getpeername( $hSocket, $sAddress, $iPort ) ? "$sAddress:$iPort" : "?????:???";
} private function log( $sMessage, $iType )
{
$sTimeStamp = @strftime( '%c' ); if( $iType == self::ERROR )
{
$aBacktrace = debug_backtrace();
$aBacktrace = $aBacktrace[1];
$sMessage = sprintf( '[%s] [E] %s%s%s [%d] : %s', $sTimeStamp, $aBacktrace['class'], $aBacktrace['type'], $aBacktrace['function'], $aBacktrace['line'], $sMessage ); if( $this->aConfig['verbosity']['echo_errors'] )
printf( "$sMessage\n" ); if( $this->aConfig['verbosity']['log_errors'] )
error_log( $sMessage );
}
else if( $iType == self::DEBUG && $this->aConfig['verbosity']['echo_debug'] )
{
echo sprintf( '[%s] [D] : %s', $sTimeStamp, $sMessage )."\n";
}
else if( $iType == self::LOG && $this->aConfig['verbosity']['echo_log'] )
{
echo sprintf( '[%s] [L] : %s', $sTimeStamp, $sMessage )."\n";
}
} /*
* Handle clients here.
*/
private function handleClientRequest( $hClient, $iClientIndex )
{
/*
* ...
*/ $this->disconnect( $iClientIndex );
} private function disconnect( $i )
{
socket_close( $this->aClients[ $i ] );
$this->aClients[ $i ] = NULL;
} private function loadConfiguration( $sConfigFile )
{
if( !is_file( $sConfigFile ) || !is_readable( $sConfigFile ) )
die( "Could not read $sConfigFile.\n" ); else if( !( $this->aConfig = parse_ini_file( $sConfigFile, TRUE ) ) )
die( "Could not parse $sConfigFile.\n" ); foreach( self::$aDefaults as $sSection => $aDefaultValues )
{
if( !isset( $this->aConfig[ $sSection ] ) )
$this->aConfig[ $sSection ] = array(); foreach( $aDefaultValues as $sName => $sValue )
{
if( !isset( $this->aConfig[ $sSection ][ $sName ] ) )
$this->aConfig[ $sSection ][ $sName ] = $sValue;
}
}
} public function setConfig( $sSectionName, $sConfigName, $mValue )
{
if( !isset( $this->aConfig[ $sSectionName ] ) )
$this->aConfig[ $sSectionName ] = array(); $this->aConfig[ $sSectionName ][ $sConfigName ] = $mValue;
} public function __construct( $sConfigFile )
{
$this->loadConfiguration( $sConfigFile ); if( !( $this->hSocket = socket_create( AF_INET, SOCK_STREAM, SOL_TCP ) ) )
$this->log( 'Could not create main socket ( '.socket_strerror( socket_last_error() ).' ).', self::ERROR ); else if( socket_set_option( $this->hSocket, SOL_SOCKET, SO_REUSEADDR, 1 ) === FALSE )
$this->log( 'Could not set SO_REUSEADDR flag ( '.socket_strerror( socket_last_error() ).' ).', self::ERROR );
} public function start()
{
if( !socket_bind( $this->hSocket, $this->aConfig['main']['address'], $this->aConfig['main']['port'] ) )
$this->log( 'Could not bind on '.$this->aConfig['main']['address'].':'.$this->aConfig['main']['port'].' ( '.socket_strerror( socket_last_error() ).' ).', self::ERROR ); else if( !socket_listen( $this->hSocket, $this->aConfig['main']['backlog'] ) )
$this->log( 'Could not put main socket in listening mode ( '.socket_strerror( socket_last_error() ).' ).', self::ERROR ); else if( !socket_set_nonblock( $this->hSocket ) )
$this->log( 'Could not set main socket in non-blocking mode ( '.socket_strerror( socket_last_error() ).' ).', self::ERROR ); else
{
$this->iStartTime = time(); $this->log( 'Server started on '.$this->aConfig['main']['address'].':'.$this->aConfig['main']['port'].' .', self::LOG ); for(;;)
{
$aRead = array_merge( array( $this->hSocket ), $this->aClients ); if( socket_select( $aRead, $aWrite, $aExcept, $this->aConfig['main']['select_timeout'] ) )
{
if( in_array( $this->hSocket, $aRead ) )
{
if( ( $hClient = @socket_accept( $this->hSocket ) ) )
{
$this->aClients[ microtime(TRUE) ] = $hClient;
$this->iLastActivity = time(); $this->log( 'New incoming connection '.self::getName( $hClient ), self::DEBUG );
}
else
$this->log( 'Could not accept a new connection ( '.socket_strerror( socket_last_error() ).' ).', self::ERROR );
}
} /*
* Search for readable clients.
*/
foreach( $this->aClients as $i => $hClient )
{
if( in_array( $hClient, $aRead ) )
{
$this->handleClientRequest( $hClient, $i );
}
} /*
* Remove closed connections.
*/
$this->aClients = array_filter( $this->aClients );
}
}
} public function __destruct()
{
if( $this->hSocket )
{
$this->log( 'Shutting down ...', self::LOG ); foreach( $this->aClients as $sId => $hClient )
{
if( $hClient )
socket_close( $hClient );
} socket_close( $this->hSocket );
} @unlink( $this->getPidFile() );
}
} ?>
php非阻塞服务器的更多相关文章
- 【IBM】Merlin 给 Java 平台带来了非阻塞 I/O
Merlin 给 Java 平台带来了非阻塞 I/O 新增的功能大幅降低了线程开销 Java 技术平台早就应该提供非阻塞 I/O 机制了.幸运的是,Merlin(JDK 1.4)有一根几乎在各个场合都 ...
- Java NIO: Non-blocking Server 非阻塞网络服务器
本文翻译自 Jakob Jenkov 的 Java NIO: Non-blocking Server ,原文地址:http://tutorials.jenkov.com/java-nio/non-bl ...
- Java NIO 非阻塞Socket服务器构建
推荐阅读IBM developerWorks中NIO的入门教程,尤其是对块I/O和流I/O不太清楚的开发者. 说到socket服务器,第一反应是java.net.Socket这个类.事实上在并发和响应 ...
- 利用Python中SocketServer 实现客户端与服务器间非阻塞通信
利用SocketServer模块来实现网络客户端与服务器并发连接非阻塞通信 版权声明 本文转自:http://blog.csdn.net/cnmilan/article/details/9664823 ...
- 非阻塞tcp服务器与阻塞的tcp服务器对比
一般的tcp服务器(阻塞)是使用的如下 [erlang] gen_tcp传输文件原型 http://www.cnblogs.com/bluefrog/archive/2012/09/10/267904 ...
- 简易非阻塞http服务器
说明 需要理解阻塞和非阻塞的区别,特别要注意非阻塞和异步不是一个概念,这个很容易弄错.云盘里面netty的书会讲这几个方面的区别,nodejs深入浅出关于异步编程章节里面 ...
- 【python】网络编程-SocketServer 实现客户端与服务器间非阻塞通信
利用SocketServer模块来实现网络客户端与服务器并发连接非阻塞通信.首先,先了解下SocketServer模块中可供使用的类:BaseServer:包含服务器的核心功能与混合(mix-in)类 ...
- 第15章 高并发服务器编程(1)_非阻塞I/O模型
1. 高性能I/O (1)通常,recv函数没有数据可用时会阻塞等待.同样,当socket发送缓冲区没有足够多空间来发送消息时,函数send会阻塞. (2)当socket在非阻塞模式下,这些函数不会阻 ...
- tornado-简单的服务器非阻塞
1.服务器 非阻塞 import tornado.ioloop import tornado.web import tornado.httpserver # 非阻塞 import tornado.op ...
随机推荐
- [PureScript] Basic Data Constructors in PureScript
PureScript types are very extensive and we are going to experiment with type constructors and how to ...
- 抽屉柜式MCC柜中PROFIBUS设备推荐波特率及相应传输距离
抽屉柜式MCC柜中PROFIBUS设备推荐波特率及相应传输距离.例如以下图所看到的: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L ...
- Dubbo-Fail to decode request due to: RpcInvocation
使用Dubbo进行服务化,遇到如下错误: Caused by: com.alibaba.dubbo.remoting.RemotingException: Fail to decode request ...
- Windows版Mycat结合mysql安装配置+水平切分(转载)
来源:https://segmentfault.com/a/1190000009495748 参考文档:Mycat安装与使用 环境 环境 版本 windows 10 java 1.8.0 mysql ...
- thinkphp3错误:syntax error, unexpected 'list' (T_LIST), expecting identifier (T_STRING)
syntax error, unexpected 'list' (T_LIST), expecting identifier (T_STRING) 出现这个错误的原因是,list是php的一个函数,系 ...
- LintCode: Search A 2d Matrix
1. 设查找的数位y,第一行最后一列的数位x 如果x<y,x是第一行最大的,所以第一行都小于y,删除第一行: 如果x>y,x是最后一列最小的,所以最后一列都大于y,删除最后一列: 这样保证 ...
- java.lang.ClassNotFoundException: SparkPi$$anonfun$1
出现这个错误可能有两种情况,Jar文件没有传上去,或者Build Path里面包含的Jar文件和Spark的运行环境有冲突. 对于第一种情况,需要在SparkConf语句后面加上Jar文件的路径: v ...
- [memory]虚拟地址空间分布
一.开篇 踏入嵌入式软件行业也接近2年了,从研一开学起懵懵懂懂的開始学习C语言.因为本科时对这方面了解的少之又少,所以学起来比較困难.可是有一群无私奉献的小伙伴,慢慢的,慢慢的,慢慢的,一仅仅脚踏进了 ...
- Java DESede 加解密("DESede/ECB/PKCS5Padding")
private static final Cipher DES_CIPHER; static { try { DES_CIPHER = Cipher.getInstance("DESede/ ...
- iOS变量定义在 .h 还是 .m 中
前言 曾经我定义变量一直都是定义在.h文件里.后来看别人的代码,发现非常多人都把一些变量定 义在.m文件里. 后来我自己试了一把,发现变量既能够定义在.h文件里也能够定义在.m文 件中,尽管这是个非常 ...