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] Break up Expressions into Cases in PureScript using Simple Pattern Matching
Pattern matching in functional programming languages is a way to break up expressions into individua ...
- jQuery对象合并、jQuery添加静态方法、jQuery添加DOM实例方法
实例效果: 代码演示: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:/ ...
- 简单实用的extend对象合并
/** * 合并对象 * 示例:o = extend({ a: 'a' }, o); */ function extend(s, t) { if (!s) { return {}; } if (!s) ...
- 微信小程序 - 组件传值给调用页面
演示如下(可以ctrl+鼠标放大或者下载GIF图片) 1. 先组件定义事件“checkbox”(组件内事件) 2. 调用页面调用它需要加bind:事件名 = 调用页面事件名(bind即绑定调用组件“o ...
- C#和网页js互调代码
C#和网页js互调代码 1.先写个网页放在主程序目录下:test.html <!DOCTYPE html> <html lang="en" xmlns=" ...
- JEECG中的validform验证ajaxurl的使用方法
validform验证是一种非常方便的,实用的验证方式 对于需要验证后台数据的,validform是一个非常明智的选择 validform的ajaxurl属性能够完美的实现:当输入完成某一输入框,就会 ...
- 常用API文档
Python requtets PyQuery Pascal Delphi PHP ThinkPHP5.0完全开发手册 ThinkPHP3.2.3快速入门
- Container [pid=6263,containerID=container_1494900155967_0001_02_000001] is running beyond virtual memory limits
以Spark-Client模式运行,Spark-Submit时出现了下面的错误: User: hadoop Name: Spark Pi Application Type: SPARK Applica ...
- windows安装python2.7后的注册(registry)问题
[提要]win平台上,python2.7官网的安装包在安装后不会添加环境变量且不会把安装信息写入注册表. 把python和pip的安装路径添加到环境变量是做python开发必要的一步,而写入注册表的原 ...
- EL表达式学习笔记
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6684424.html 一:EL表达式的用途 1.获取数据:(某个web域 中的对象,访问javabean的 ...