Created
December 23, 2015 14:37
-
-
Save maple-nishiyama/1df91e1ea30da6f99840 to your computer and use it in GitHub Desktop.
PHP で多重化エコーサーバー
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
error_reporting(E_ALL); | |
set_time_limit(0); | |
ob_implicit_flush(); | |
function main() { | |
// デーモン化 | |
daemonize(); | |
$address = '127.0.0.1'; | |
$port = 10000; | |
// サーバーソケット作成 | |
$sock = server_socket($address, $port); | |
// 接続待ち受けループに入る | |
accept_loop($sock); | |
socket_close($sock); | |
} | |
function daemonize() { | |
// PHPのプロセスをデーモン状態にする | |
$pid = pcntl_fork(); | |
if ($pid < 0) { | |
die("フォーク失敗\n"); | |
} else if ($pid > 0) { | |
// 親プロセス | |
exit(); | |
} | |
// 子プロセス | |
// 制御端末の切り離し | |
$sid = posix_setsid(); | |
if ($sid < 0) { | |
die("セッションを生成できませんでした。\n"); | |
} | |
// セッションリーダーでなくする | |
// 2回めの fork() | |
$pid2 = pcntl_fork(); | |
if ($pid2 < 0) { | |
die("2回めのフォーク失敗\n"); | |
} else if ($pid2 > 0) { | |
// 子プロセス | |
exit(); | |
} | |
// 孫プロセス | |
// ルートディレクトリをカレントディレクトリへ | |
chdir("/"); | |
// 標準入出力を閉じる | |
fclose(STDIN); | |
fclose(STDOUT); | |
fclose(STDERR); | |
// デーモンになった! | |
} | |
function server_socket($address, $port) { | |
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) { | |
die("socket_create() に失敗\n"); | |
} | |
if (socket_bind($sock, $address, $port) === false) { | |
die("socket_bind() に失敗\n"); | |
} | |
if (socket_listen($sock, 5) === false) { | |
die("socket_listen() に失敗\n"); | |
} | |
return $sock; | |
} | |
function accept_loop($sock) { | |
while (true) { | |
if (($msgsock = socket_accept($sock)) === false) { | |
dir("socket_accept() に失敗\n"); | |
break; | |
} | |
// プロセスフォーク | |
$pid = pcntl_fork(); | |
if ($pid < 0) { | |
die("fork() に失敗\n"); | |
} else if ($pid > 0) { | |
// 親プロセス:メッセージのやり取りは子に任せるのでアクセプトソケットをクローズ | |
socket_close($msgsock); | |
$msgsock = null; | |
} else { | |
// 子プロセス:サーバーソケットは使わないのでクローズ | |
socket_close($sock); | |
// メッセージループに入る | |
message_loop($msgsock); | |
socket_close($msgsock); | |
exit(0); | |
} | |
} | |
} | |
function message_loop($msgsock) { | |
$msg = "\nWelcome to the PHP Test Server.\n" . | |
"To quit, type 'quit'. To shut down the server type 'shutdown'\n"; | |
socket_write($msgsock, $msg, strlen($msg)); | |
while (true) { | |
if (($buf = socket_read($msgsock, 2048, PHP_NORMAL_READ)) === false) { | |
echo "socket_read() に失敗\n"; | |
return -1; | |
} | |
if (!$buf = trim($buf)) { | |
continue; | |
} | |
if ($buf == 'quit') { | |
break; | |
} | |
if ($buf == 'shutdown') { | |
socket_close($msgsock); | |
return -1; | |
} | |
$talkback = "PHP: You said '$buf'.\n"; | |
socket_write($msgsock, $talkback, strlen($talkback)); | |
//echo "$buf\n"; | |
} | |
} | |
main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment