PHPのネットワークサーバ
Rubyでネットワークサーバを書く
を読んでみてふと。
一応、PHPでもネットワークサーバを書こうと思えば書けるので習作として。
参考にしたページ。
PHP V5 でマルチタスク動作のアプリケーションを開発するとか
stream_socket_serverとか。
(参考というよりほぼ丸ぱくり)
というか全然最適化してないです。
デーモンでもない。
デーモンプロセスのヒ・ミ・ツとか見てみたけど、そもそもデーモンプロセスである利点がいまいちピンとこない。
ちなみにPHPでもデーモンは書けるらしい。
(今さっき気付いた)
PHPでデーモンプロセス
ソケット関数
(本当はシグナル処理とかいるのだろうけど)
下の関数を呼び出すとデーモンになるみたいだ。
[php]
function become_daemon() {
$child = pcntl_fork();
if($child) {
exit; // kill parent
}
posix_setsid(); // become session leader
chdir("/");
umask(0); // clear umask
return posix_getpid();
}[/php]
思うにTCPサーバはメモリリークとか気をつけるところさえ気をつけてしまえば、Cなどではなくスクリプト系で書いてしまってもいいような気がしてきた。
ストリーム処理は別にしても、PHPで書くのもCで書くのとなんだか同じような感じの気もする。
そもそも PEARに使えそうなクラスがありそうな気がするが。
[php]
!/usr/bin/php -q
<?php
$url = 'tcp://0.0.0.0:8701'; $usec = 500000; $names = array();
$server = stream_socket_server($url, $errno, $errstr); if (!$server) { die("$errstr ( $errno) \n"); }
echo "$url start\n"; $streams = array($server);
while(true) { $r = $streams; $s = stream_select($r, $w = NULL, $e = NULL, $usec); if ($s === FALSE) { break; } for ($i=0;$i<$s;$i++) { if ($r[$i] === $server) { $conn = stream_socket_accept($server); $streams[] = $conn; $users[$conn] = array(); continue; } $data = fread($r[$i], 4096); if (empty($data)) { fclose($r[$i]); $k = array_search($r[$i], $streams, TRUE); if ( $k !== FALSE) { unset($streams[$k]); } $k = array_search($r[$i], $names, TRUE); if ($k !== FALSE) { unset($names[$k]); } continue; } // receive data echo $data; // 'name:hogehoge' if (preg_match('/^name:(.+)$/', $data, $m)) { $name = trim($m[1]); if (isset($names[$name])){ fwrite($r[$i], "used $name\n"); } else { $names[$name] = $r[$i]; fwrite($r[$i], "set name $name\n"); } continue; } $k = array_search($r[$i], $names, TRUE); $from = ($k !== FALSE) ? $k : 'none'; // 'to hogehoeg:message' if (preg_match('/^to ([^:]+):(.+)$/', $data, $m)){ $name = trim($m[1]); if (isset($names[$name])) { fwrite($names[$name], "from $from:" . trim($m[2]) . "\n"); } continue; } } }
exit();[/php]