linux下php多进程与可响应http请求的socket server

  要有多蛋疼才会用php去写http服务器?答案是需要蛋疼到蛋裂的地步。

  还好哥只是略疼,所以写了非常非常粗糙的一点东西,目的是为了温习下php的socket(tcp)+fork的用法。

  开始先讲原理,主要是scoket服务利用whilet挂住,socket_accept接收到新的socket连接后,马上fork一个子进程,负责单独和这个连接交互,这里也很简单,无非就是socket_read挂住监听这个连接的请求,发现有则解析并返回,这里说的返回是socket_write往socket连接的句柄写入信息。

  接着就是代码了,解释再多也不如代码看得实在。

#!/usr/local/php/bin/php
<?php
$host = "192.168.1.50"; $port = 12335;
set_time_limit(0);
// Socket create
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("Could not create socket\n");
// Bind socket to a port
$result = socket_bind($socket, $host, $port) or die("Could not bind to socket\n");
// Start listening for connections
$result = socket_listen($socket, 3) or die("Could not set up socket listener\n");

while( true )
{
/** waiting a new connection **/
$newsock = socket_accept( $socket );
/**
***We fork child process for each client
*
*/
if($newsock)
{
$child = pcntl_fork();
if( $child > 0 )
{//parent process.
/**
** Since child process is hanging there.
** so we know that we should close client socket here.
*
*/
socket_close( $newsock );
}
else if( $child == 0 )
{//child process
/** get address and port of client socket **/
socket_getpeername($newsock,$addr,$port);
$welcomemsg = "A new clients $addr:$port was entered.".PHP_EOL;
echo $welcomemsg;
while( true )
{
/** hanging here to wait some messages come from client socket **/
$msg = socket_read( $newsock,1024);
if( $msg === false)
{
/** Client was quited unexpected **/
echo "$addr:$port was quited!".PHP_EOL;
socket_close( $newsock );
posix_kill( posix_getpid(),SIGTERM);
}
else
{
$kill = false;
$msg = strtolower(trim($msg));
/** Cli hello message **/
if(!empty($msg) && $msg != "\x21\x23") echo "$addr:$port request:".$msg.PHP_EOL;
/** Do something according to command from client **/
switch( $msg )
{
default :
if(preg_match('#^(get|post)\s+/([^\s]*)#i',$msg,$match))
{//it's a http request
$page = $match[2] ? $match[2] : 'index.php';
ob_start();
include '/var/www/'.$page;
$httpResponse = ob_get_contents();
ob_end_clean();
//$httpResponse = "<b>Hello browser,成功了!</b>";
$msg = "HTTP/1.1 200\n"
."Content-type:text/html;charset=utf-8\n"
."Content-length:".strlen($httpResponse)."\n"
."Connection:close\n\n"
.$httpResponse;
$kill = true;
}
else $msg = "Unknow command!";
break;
case "\x21\x23":
$msg = "Welcome $addr:$port";
break;

case 'q':
case 'quit':
case 'exit':
echo "$addr:$port ask for quit!".PHP_EOL;
break;
}
/** Message send to client socket,
*** would kill client socket when wrote action was fail or when we doing a http response*
*/
if(!socket_write($newsock,$msg,strlen($msg)) || $kill)
{
echo "$addr:$port was quited!".PHP_EOL;
socket_close( $newsock );
posix_kill( posix_getpid(),SIGTERM);
}
}
}
}
else
{//
exit('Unable to fork!');
}
}
}
// close sockets
socket_close($socket);
?>

  非常简单吧!正如之前所说的那样,什么?还想真的完成http请求的解析+依托cgi响应返回,丫没病吧。

  赶紧来试验下简单的东西,首先启动这个socket server服务

  启动服务器

       然后先浏览80端口服务器的的某个html页面

  80服务器

 

       然后看看php的scoket server响应效果

  php socket服务器

  宾了个果,妥了个妥地,再打开一个浏览器tab页面,输入这个地址+端口一样可以正确看到效果。

  而且也看到了浏览器往我们傻缺的php http server服务器请求了以下信息。

  请求信息

  接下来如何改进这个php socket server玩玩好玩的东西呢?想到再说吧。

posted @ 2012-04-06 20:30  一缕青烟  阅读(3185)  评论(3编辑  收藏  举报