add http server sample

This commit is contained in:
Shuhei Tanuma 2012-07-01 21:58:12 +09:00
parent c80410fb08
commit db85553439
3 changed files with 157 additions and 112 deletions

10
examples/debug_timer.php Normal file
View File

@ -0,0 +1,10 @@
<?php
$timer = uv_timer_init();
$stat = array();
$stat['begin'] = memory_get_usage();
uv_timer_start($timer, 10, 1000, function($stat, $timer) use (&$stat){
$stat["current"] = memory_get_usage();
printf("memory: %d\n", $stat["current"] - $stat['begin']);
});

140
examples/http.php Normal file
View File

@ -0,0 +1,140 @@
<?php
/**
* TODO: this implementation is not correct some error handling.
*/
function createServer(Closure $closure)
{
$server = new HttpServer();
$server->addListener($closure);
return $server;
}
class HttpResponse
{
protected $server;
protected $client;
protected $code = 200;
protected $headers = array();
protected $body = array();
protected $http_version = "1.0";
public function __construct($server, $client)
{
$this->server = $server;
$this->client = $client;
}
public function writeHead($code, array $headers)
{
$this->code = $code;
$this->headers = $headers;
}
public function write($data)
{
$this->body[] = $data;
}
public function end()
{
// Todo: implement correctly
$buffer = "HTTP/1.0 200 OK\r\n";
foreach ($this->headers as $key => $value) {
$buffer .= $key . ": " . $value . "\r\n";
}
$buffer .= "\r\n";
$buffer .= join("", $this->body);
uv_write($this->client, $buffer, array($this->server, "onWrite"));
}
}
class HttpServer
{
protected $server;
protected $clients = array();
protected $parsers = array();
protected $closure;
public function __construct()
{
$this->server = uv_tcp_init();
}
public function addListener($closure)
{
$this->closure = $closure;
}
public function onShutdown($handle)
{
uv_close($handle, array($this, "onClose"));
}
public function onClose($handle)
{
unset($this->clients[(int)$handle]);
unset($this->parsers[(int)$handle]);
}
public function onWrite($status, $client)
{
if ($status == 0) {
uv_shutdown($client, array($this, "onShutdown"));
} else {
echo "[write_failed]";
}
}
public function onRead($client, $buffer, $nread)
{
//echo $buffer;
//echo "--Error: " . uv_err_name(uv_last_error(uv_default_loop())) . PHP_EOL;
if ($nread < 0) {
//echo "[NREAD={$nread}]\n";
uv_shutdown($client, array($this, "onShutdown"));
} else if ($nread == 0) {
// nothing to do.
//echo "[NREAD=0]\n";
} else {
$result = array();
if (uv_http_parser_execute($this->parsers[(int)($client)], $buffer, $result)){
$response = new HttpResponse($this, $client);
$closure = $this->closure;
$closure($result, $response);
} else {
// nothing to do. (waiting next buffer)
}
}
}
public function onConnect($server)
{
$client = uv_tcp_init();
uv_tcp_nodelay($client, 1);
uv_accept($server,$client);
$this->clients[(int)$client] = $client;
$this->parsers[(int)($client)] = uv_http_parser_init();
uv_read_start($client, array($this, "onRead"));
}
public function listen($port)
{
uv_tcp_nodelay($this->server, 1);
uv_tcp_bind6($this->server, uv_ip6_addr("::1",$port));
uv_listen($this->server, 511, array($this, "onConnect"));
uv_run(uv_default_loop());
}
}

View File

@ -1,114 +1,9 @@
<?php
/* do we need these function ? */
ob_implicit_flush(true);
ob_end_flush();
require "http.php";
require "debug_timer.php";
global $servers;
$servers = 0;
$timer = uv_timer_init();
$stat = array();
$stat['begin'] = memory_get_usage();
uv_timer_start($timer, 10, 1000, function($stat, $timer) use (&$stat){
global $servers;
$stat["current"] = memory_get_usage();
printf("memory: %d\n", $stat["current"] - $stat['begin']);
printf("servers: %d\n", $servers);
});
$server = uv_tcp_init();
uv_tcp_bind6($server,uv_ip6_addr("::1",8888));
uv_tcp_nodelay($server, 1);
function on_connect($server)
{
global $servers;
global $parsers;
echo "[LISTEN]" . PHP_EOL;
$client = uv_tcp_init();
uv_tcp_nodelay($client, 1);
uv_accept($server,$client);
$servers++;
echo "-Error: " . uv_err_name(uv_last_error(uv_default_loop())) . PHP_EOL;
echo "[Accept]" . PHP_EOL;
$parsers[(int)($client)] = uv_http_parser_init();
uv_read_start($client, "on_read");
}
function on_read($client, $buffer, $nread)
{
//echo $buffer;
echo "--Error: " . uv_err_name(uv_last_error(uv_default_loop())) . PHP_EOL;
global $parsers;
if ($nread < 0) {
echo "[NREAD={$nread}]\n";
uv_shutdown($client, "on_shutdown");
} else if ($nread == 0) {
// nothing to do.
echo "[NREAD=0]\n";
} else {
$result = array();
echo "parser" . PHP_EOL;
if (uv_http_parser_execute($parsers[(int)($client)], $buffer, $result)){
echo $buffer;
echo PHP_EOL;
$response = "HTTP/1.0 200 OK
Pragma: no-cache
Accept-Ranges: bytes
Content-Length: 6
Connection: close
Content-Type: text/html
Hello
";
echo $response;
uv_write($client,$response,"on_write");
} else {
// nothing todo. (waiting next buffer)
}
}
}
function on_shutdown($handle)
{
global $parsers;
global $servers;
$servers--;
unset($parsers[(int)$handle]);
echo "shutdown" . PHP_EOL;
uv_close($handle, function($handle){
echo "=close\n";
});
}
function on_shutdown2($handle)
{
uv_close($handle,function($handle){echo "==close\n";});
}
function on_write($status, $client)
{
global $servers;
global $parsers;
$servers--;
unset($parsers[(int)$client]);
if ($status == 0) {
uv_shutdown($client, "on_shutdown2");
} else {
echo "[write_failed]";
}
}
uv_listen($server, 127, "on_connect");
uv_run();
createServer(function($request, $response){
$response->writeHead(200, array("Content-Type" => "text/plain"));
$response->write("Hello World");
$response->end();
})->listen(8888);