PHP Socket Programming Handbook 読書メモ PHPによるソケットプログラミング

php_socket_programming_handbook


はじめに

本書を読むにあたり必要なものは以下の通り

  • Windows以外のOS(WindowsではUNIXソケットの機能の一部は使用できない)
  • コマンドライン
  • ncコマンド

やり方はひとつじゃない(TIMTOWTDI)

  • TIMTOWTDI = “There’s more than one way to do it”
  • PHPでのソケットプログラミングには2つのやり方がある

ソケット拡張

  • ソケット拡張はコンパイル時のデフォルトでは無効
  • ソケット拡張で作成したソケットリソースはsocket_xxx関数からのみ利用可能
  • UNIXのシステムコールに近い形式のAPI
  • (本書の著者は)使用を推奨しない

ストリームソケット

  • ストリーム拡張はPHP 5以降ではデフォルトで有効
  • PHP 5以降では、ストリーム(Stream)APIがソケットを扱える
  • ストリームAPIで作成したソケットリソースはファイル系の関数で扱える
  • ソケットの低レベルでの制御はできない
  • 原則として、ストリームAPIを使用してソケットを扱うべき

エコーサーバの例

古典的なサーバプログラムの処理は以下のようになる:

  1. ソケットにbindする
  2. ソケットをlistenし、コネクションを待ち受ける
  3. コネクションをacceptする
  4. クライアントが送信したデータを受け取る
  5. レスポンスを返す
  6. コネクションを切断するか、クライアントが切断するまで待つ
  7. 3に戻る

実装

<?php

// echo.php
// 本書のサンプルコードを一部修正している

$server = @stream_socket_server('tcp://0.0.0.0:1337', $errno, $errstr);

if (false === $server) {
    fwrite(STDERR, "Error: $errno: $errstr\n");
    exit(1);
}

$timeout = -1; // タイムアウトしないようにする
$readLength = 4096;

for (;;) {
    $conn = @stream_socket_accept($server, $timeout, $peer);

    if ($conn) {
        while ($buf = fread($conn, $readLength)) {
            fwrite($conn, $buf);
        }
        fclose($conn);
    }
}
  • stream_socket_serverは、ステップ1と2を実行する
  • for (;;)で無限ループを作り、内部でstream_socket_acceptでコネクションを待ち受ける(ステップ3)
  • freadでデータを読み取り(ステップ4)
  • fwriteでデータ書き込み(ステップ5)
  • fcloseでソケットを閉じる(ステップ6)

サーバの実行

  • php echo.php で起動できる
  • 初回起動時にはポート開放が必要になる
  • クライアント(netcat)はnc 127.0.0.1 1337で接続できる

コメントをどうぞ

コメントを残す