Skip to content

Instantly share code, notes, and snippets.

@maple-nishiyama
Created January 21, 2016 11:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maple-nishiyama/247de0a040e704115264 to your computer and use it in GitHub Desktop.
Save maple-nishiyama/247de0a040e704115264 to your computer and use it in GitHub Desktop.
PHP libevent で多重化エコーサーバー ref: http://qiita.com/d_nishiyama85/items/7e9a72a69f90487a892d
$ sudo yum install libevent
$ sudo yum install libevent-devel
$ sudo yum install php-pear
$ sudo pecl install "channel://pecl.php.net/libevent-0.1.0"
extension=libevent.so
<?php
function print_line($fd, $events, $arg)
{
static $max_requests = 0;
$max_requests++;
if ($max_requests == 10) {
// 10 回書き込んだらループを抜けます
event_base_loopexit($arg[1]);
}
// 行を表示します
echo fgets($fd);
}
// ベースとイベントを作成します
$base = event_base_new();
$event = event_new();
$fd = STDIN;
// イベントフラグを設定します
event_set($event, $fd, EV_READ | EV_PERSIST, "print_line", array($event, $base));
// イベントベースを設定します
event_base_set($event, $base);
// イベントを有効にします
event_add($event);
// イベントループを開始します
event_base_loop($base);
?>
$base = event_base_new();
$eb = event_buffer_new(STDIN, "print_line", NULL, "error_func", $base);
event_buffer_base_set($eb, $base);
event_buffer_enable($eb, EV_READ);
event_base_loop($base);
<?php
// サーバーソケットの作成
$socket = stream_socket_server('tcp://0.0.0.0:8000', $errno, $errstr);
if (!$socket) {
die("$errstr ($errno)\n");
}
stream_set_blocking($socket, 0);
$base = event_base_new();
$event = event_new();
event_set($event, $socket, EV_READ | EV_PERSIST, 'ev_accept', $base);
event_base_set($event, $base);
event_add($event);
event_base_loop($base);
// 接続中のクライアントを管理する変数
$GLOBALS['connections'] = [];
// クライアントの接続をバッファリングするオブジェクトを管理する変数
$GLOBALS['buffers'] = [];
// サーバーソケットに接続が来たときに呼ばれるコールバック
function ev_accept($socket, $flag, $base) {
static $id = 0;
$conn = stream_socket_accept($socket);
stream_set_blocking($conn, 0);
$id += 1;
echo "client connected.\n";
// welcome メッセージを送信
$welcome = "welcome to simple php echo server!\n";
fwrite($conn, $welcome, strlen($welcome));
// クライアントの監視をイベントループに追加(バッファつきイベントの作成)
$buffer = event_buffer_new($conn, 'ev_read', NULL, 'ev_error', $id);
event_buffer_base_set($buffer, $base);
event_buffer_timeout_set($buffer, 30, 30);
event_buffer_watermark_set($buffer, EV_READ, 0, 0xffffff);
event_buffer_priority_set($buffer, 10);
event_buffer_enable($buffer, EV_READ | EV_PERSIST);
$GLOBALS['connections'][$id] = $conn;
$GLOBALS['buffers'][$id] = $buffer;
}
// エラー処理コールバック
function ev_error($buffer, $error, $id) {
event_buffer_disable($GLOBALS['buffers'][$id], EV_READ | EV_WRITE);
event_buffer_free($GLOBALS['buffers'][$id]);
fclose($GLOBALS['connections'][$id]);
unset($GLOBALS['buffers'][$id], $GLOBALS['connections'][$id]);
echo "connection $id closed.\n";
}
// クライアントソケットが読み取り可能になった(メッセージが届いた)ときに呼ばれるコールバック
function ev_read($buffer, $id) {
while ($read = event_buffer_read($buffer, 4096)) {
echo "message receive: $read";
// エコーバックする
event_buffer_write($buffer, $read);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment