socket服务的模型以及实现–单进程IO复用select
Posted 飞鸿影的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了socket服务的模型以及实现–单进程IO复用select相关的知识,希望对你有一定的参考价值。
利用多进程来提高并发连接数并不理想,进程消耗太大了,这次我们利用IO复用技术来实现。
<?php
/**
* 单进程IO复用select
* 同时处理多个连接
*/
class Xtgxiso_server
{
public $socket = false;
public $master = array();
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);
stream_set_blocking($this->socket,0);
$id = (int)$this->socket;
$this->master[$id] = $this->socket;
}
public function run(){
$read = $this->master;
$receive = array();
echo "start run...\n";
while ( 1 ) {
$read = $this->master;
//echo "waiting...\n";
$mod_fd = @stream_select($read, $_w = NULL, $_e = NULL, 60);
if ($mod_fd === FALSE) {
break;
}
foreach ( $read as $k => $v ) {
if ( $v === $this->socket ) {
//echo "new conn\n";
$conn = stream_socket_accept($this->socket);
if($this->onConnect) {
call_user_func($this->onConnect, $conn);
}
$id = (int)$conn;
$this->master[$id] = $conn;
} else {
//echo "read data\n";
if ( !isset($receive[$k]) ){
$receive[$k]="";
}
$buffer = fread($v, 10);
//echo $buffer."\n";
if ( strlen($buffer) === 0 ) {
if ( $this->onClose ){
call_user_func($this->onClose,$v);
}
fclose($v);
$id = (int)$v;
unset($this->master[$id]);
} else if ( $buffer === FALSE ) {
if ( $this->onClose ){
call_user_func($this->onClose, $this->master[$key_to_del]);
}
fclose($v);
$id = (int)$v;
unset($this->master[$id]);
} else {
$pos = strpos($buffer, "\n");
if ( $pos === false) {
$receive[$k] .= $buffer;
//echo "received:".$buffer.";not all package,continue recdiveing\n";
}else{
$receive[$k] .= trim(substr ($buffer,0,$pos+1));
$buffer = substr($buffer,$pos+1);
if($this->onMessage) {
call_user_func($this->onMessage,$v,$receive[$k]);
}
switch ( $receive[$k] ){
case "quit":
echo "client close conn\n";
fclose($v);
$id = (int)$v;
unset($this->master[$id]);
break;
default:
//echo "all package:\n";
//echo $receive[$k]."\n";
break;
}
$receive[$k]='';
}
}
}
}
usleep(10000);
}
}
}
$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();
这样我们同时处理的连接数就不受限于进程数了,相对于靠多进程来提高连接数的方式明显好了很多。
以上是关于socket服务的模型以及实现–单进程IO复用select的主要内容,如果未能解决你的问题,请参考以下文章