Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】stream_socket_server()関数の使い方

stream_socket_server関数の使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

stream_socket_server関数は、ネットワーク上でクライアントからの接続を受け入れるためのサーバーソケットを作成し、接続待機状態にする関数です。この関数を使用することで、PHPスクリプトをネットワークサーバーとして機能させ、他のプログラムやクライアントからの通信を待ち受けることが可能になります。

具体的には、local_socketという引数で、どのプロトコル(例えば、tcp://udp://)を使って、どのIPアドレスとポート番号(例えば、127.0.0.1:8000)で接続を待つのかを指定します。これにより、TCP/IPプロトコルだけでなく、UDPプロトコルやUnixドメインソケットなど、様々な種類のサーバーソケットを作成することができます。

関数が正常に実行された場合、クライアントからの接続を待ち受けるための『ストリームリソース』が返されます。このストリームリソースは、実際にクライアントが接続を試みてきた際に、その接続を受け入れるための別の関数(例えば stream_socket_accept)に渡して使用します。これにより、クライアントとの具体的な通信経路を確立することができます。

もしソケットの作成に失敗した場合は、この関数はfalseを返します。その際、errnoerrstrという引数を使用することで、なぜ失敗したのかというエラーコードとエラーメッセージの詳細な情報を取得し、適切なエラー処理を行うことができます。

この関数は、ウェブサーバーのような常に特定のポートで接続を待ち受け、データを受け取ったり応答を返したりするような、ネットワークを利用したアプリケーションをPHPで開発する際の基盤として非常に重要な役割を担っています。

構文(syntax)

1stream_socket_server(
2    string $address,
3    ?int &$error_code = null,
4    ?string &$error_message = null,
5    int $flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN,
6    ?resource $context = null
7): resource|false

引数(parameters)

string $address, ?int &$error_code = null, ?string &$error_message = null, int $flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, ?resource $context = null

  • string $address: サーバーがバインドするアドレスとポートを指定する文字列。例: "tcp://127.0.0.1:8000" や "udp://:9000"
  • ?int &$error_code = null: エラーが発生した場合にエラーコードが格納される整数型の変数への参照。
  • ?string &$error_message = null: エラーが発生した場合にエラーメッセージが格納される文字列型の変数への参照。
  • int $flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN: サーバーの動作を制御するフラグ。デフォルトはバインドとリスニング。
  • ?resource $context = null: ストリームコンテキストを指定するリソース。

戻り値(return)

resource|false

成功した場合、ソケットリソースを返します。失敗した場合は false を返します。

サンプルコード

PHP stream_socket_server でサーバーを起動する

1<?php
2
3// ソケットサーバーのアドレス
4$address = "tcp://127.0.0.1:8000";
5
6// エラーコードとエラーメッセージを格納する変数
7$error_code = 0;
8$error_message = '';
9
10// ソケットサーバーを作成
11$server = stream_socket_server(
12    $address,
13    $error_code,
14    $error_message,
15    STREAM_SERVER_BIND | STREAM_SERVER_LISTEN
16);
17
18// サーバー作成に失敗した場合
19if (!$server) {
20    echo "Failed to create server: " . $error_message . " (" . $error_code . ")\n";
21    exit(1);
22}
23
24echo "Server listening on " . $address . "\n";
25
26// クライアントからの接続を待ち受ける
27while (true) {
28    // クライアントからの接続を受け入れる
29    $client = stream_socket_accept($server, -1);
30
31    if ($client) {
32        echo "Client connected\n";
33
34        // クライアントからのデータを読み込む
35        $data = fread($client, 1024);
36        echo "Received: " . $data . "\n";
37
38        // クライアントにデータを送信する
39        fwrite($client, "Hello, client!\n");
40
41        // クライアントとの接続を閉じる
42        fclose($client);
43        echo "Client disconnected\n";
44    }
45}
46
47// サーバーソケットを閉じる (通常は到達しない)
48fclose($server);

このサンプルコードは、PHPのstream_socket_server関数を使用してシンプルなTCPソケットサーバーを構築する方法を示しています。stream_socket_server関数は、指定されたアドレスでサーバーソケットを作成し、クライアントからの接続を待ち受けます。

stream_socket_server関数の第一引数 $address には、サーバーがリッスンするアドレス(例:tcp://127.0.0.1:8000)を指定します。第二引数 $error_code と第三引数 $error_message は、それぞれエラーコードとエラーメッセージを受け取るための変数です。サーバーの作成に失敗した場合、これらの変数にエラー情報が格納されます。第四引数 $flags は、ソケットの動作を制御するためのフラグです。ここでは STREAM_SERVER_BINDSTREAM_SERVER_LISTEN を組み合わせて、アドレスにバインドし、接続をリッスンするサーバーソケットを作成しています。第五引数 $context は、ソケットコンテキストを指定します。省略した場合はデフォルトのコンテキストが使用されます。

関数が成功すると、リソース型のソケットが返されます。失敗した場合は false が返されます。

サンプルコードでは、まずstream_socket_server関数を使ってサーバーソケットを作成し、エラーが発生した場合はエラーメッセージを出力して終了します。サーバーが正常に作成された場合は、クライアントからの接続を待ち受けるループに入ります。stream_socket_accept関数でクライアントからの接続を受け入れ、クライアントからデータを受信し、メッセージを送信して接続を閉じます。最後にサーバーソケットを閉じます。

このコードは、ネットワークプログラミングの基礎を学ぶ上で役立ちます。

stream_socket_server関数を使う際の注意点です。まず、$addressは、利用可能なプロトコル(tcp、udpなど)とIPアドレス、ポート番号を正しく指定する必要があります。ポート番号が他のプロセスで使用されていないか確認してください。$error_code$error_messageは、サーバー作成に失敗した場合の原因特定に役立ちます。必ずエラー処理を行いましょう。STREAM_SERVER_BIND | STREAM_SERVER_LISTENフラグは、ソケットをアドレスにバインドし、接続をlisten状態にするために重要です。このサンプルコードは無限ループでクライアントを待ち受けるため、プログラムを停止するには明示的な終了処理が必要です。本番環境では、接続数制限やタイムアウト処理などを実装し、セキュリティとリソース管理を強化してください。

PHP stream_socket_server でTCPサーバーを構築する

1<?php
2
3/**
4 * 指定されたアドレスでTCPサーバーを起動し、クライアントからの接続を処理します。
5 *
6 * @param string $address サーバーがリッスンするアドレス。例: "tcp://127.0.0.1:8000"
7 * @param int $maxConnections 受け付ける最大接続数。この数に達するとサーバーはシャットダウンします。
8 *                            (0を指定すると無限に接続を受け付けますが、この例では推奨しません)
9 * @return void
10 */
11function createSimpleTcpServer(string $address, int $maxConnections = 1): void
12{
13    // サーバーソケットの作成中に発生したエラーを格納するための変数
14    $errorCode = null;
15    $errorMessage = null;
16
17    // stream_socket_server() 関数を使ってサーバーソケットを作成します。
18    // 第1引数: サーバーが接続を待機するアドレスを指定します。
19    // 第2引数: エラーコードが設定される変数への参照。
20    // 第3引数: エラーメッセージが設定される変数への参照。
21    // 第4引数: ソケットの振る舞いを定義するフラグ。STREAM_SERVER_BIND はアドレスにバインドし、
22    //          STREAM_SERVER_LISTEN は接続を待ち受け可能にします。
23    $server = stream_socket_server($address, $errorCode, $errorMessage, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN);
24
25    // サーバーソケットの作成に失敗した場合の処理
26    if ($server === false) {
27        echo "エラー: サーバーの起動に失敗しました。\n";
28        echo "  コード: {$errorCode}\n";
29        echo "  メッセージ: {$errorMessage}\n";
30        return; // 関数を終了し、処理を停止
31    }
32
33    echo "サーバーが起動しました: {$address}\n";
34    echo "クライアントからの接続を待機中... (最大 {$maxConnections} 接続)\n";
35
36    $connectionsCount = 0;
37
38    // クライアントからの接続を待ち受けるループ
39    // 指定された最大接続数に達するまでループを続行します
40    while ($connectionsCount < $maxConnections) {
41        // stream_socket_accept() 関数でクライアントからの接続を受け入れます。
42        // この関数は、新しい接続があるまで処理をブロック(待機)します。
43        // 成功するとクライアントソケットのリソースを、失敗すると false を返します。
44        $client = stream_socket_accept($server);
45
46        // クライアント接続が正常に確立した場合の処理
47        if ($client) {
48            $connectionsCount++; // 接続数をカウントアップ
49            echo "クライアントが接続しました ({$connectionsCount}/{$maxConnections})\n";
50
51            // クライアントにメッセージを送信します。
52            $message = "Hello from PHP server! (Connection {$connectionsCount})\n";
53            fwrite($client, $message);
54            echo "メッセージを送信しました: '{$message}'\n";
55
56            // 必要であれば、ここでクライアントからのデータを受信したり、他の処理を行うことができます。
57            // 例: $input = fread($client, 1024);
58
59            // クライアントソケットを閉じます。
60            // 接続が不要になったらリソースを解放することが重要です。
61            fclose($client);
62            echo "クライアント接続を閉じました。\n";
63        } else {
64            // 何らかの理由で接続の受け入れに失敗した場合(例: タイムアウト、または他のエラー)
65            echo "クライアント接続の受け入れに失敗しました。\n";
66            // 実際にはここでエラーログを記録したり、再試行ロジックを入れることがあります。
67        }
68    }
69
70    echo "指定された最大接続数 ({$maxConnections}) に達しました。\n";
71    echo "サーバーをシャットダウンします。\n";
72    // サーバーソケットを閉じます。
73    // これにより、新しい接続の待ち受けが停止し、リソースが解放されます。
74    fclose($server);
75    echo "サーバーがシャットダウンしました。\n";
76}
77
78// --- サーバーの実行例 ---
79// ローカルホスト (127.0.0.1) のポート8000でサーバーを起動し、
80// 最大3つのクライアント接続を処理したら終了します。
81createSimpleTcpServer("tcp://127.0.0.1:8000", 3);
82
83// このサーバーに接続するには、別のターミナルから以下のコマンドを実行します。
84// Linux/macOS:
85//   nc 127.0.0.1 8000
86// Windows (PowerShell):
87//   Test-NetConnection -ComputerName 127.0.0.1 -Port 8000
88// または、ブラウザで 'http://127.0.0.1:8000' にアクセスしてみることもできますが、
89// これはTCP接続でありHTTPプロトコルではないため、ブラウザはエラーを表示します。
90// 最も簡単なのは 'nc' コマンドの使用です。

PHPのstream_socket_server関数は、TCPやUDPなどのネットワーク通信において、クライアントからの接続を待ち受けるサーバーソケットを作成するために使用されます。

この関数は、第1引数$addressで「tcp://127.0.0.1:8000」のようにプロトコル、IPアドレス、ポートを指定し、サーバーがリッスンする場所を定義します。オプションの第2引数&$error_codeと第3引数&$error_messageには、サーバーソケット作成中に問題が発生した場合のエラー情報が格納されます。第4引数$flagsには、アドレスへのバインド(STREAM_SERVER_BIND)と接続待ち受け(STREAM_SERVER_LISTEN)を指示するフラグを組み合わせます。関数が成功すると、サーバーソケットを表すリソースを返しますが、失敗した場合はfalseを返します。

サンプルコードでは、createSimpleTcpServer関数がstream_socket_serverを使ってTCPサーバーを起動し、エラー処理も行っています。サーバーが正常に起動すると、stream_socket_accept関数でクライアントからの接続を待ち受けます。接続があった場合、クライアントにメッセージを送信し、fcloseでそのクライアントとの接続を閉じます。指定された接続数を処理し終えると、最終的にfcloseでサーバーソケットも閉じ、すべてのリソースを解放します。これにより、PHPでネットワークサーバーを構築する基本的な流れを学ぶことができます。

このサンプルコードでは、サーバーの起動確認とエラーメッセージの出力が非常に重要です。ポートが既に使用されているなど、サーバー起動失敗の原因は様々です。必ずエラー変数を確認し対応してください。また、stream_socket_serverstream_socket_acceptで開かれたソケットリソースは、処理が終わったら必ずfclose()で閉じてください。閉じ忘れるとリソースリークやポートの再利用に支障をきたします。stream_socket_accept()はクライアントからの接続を待つ間、プログラムの実行を一時停止(ブロック)します。多数の接続を同時に扱う場合は、非同期I/Oなど、より高度な実装を検討してください。このサーバーはTCPプロトコルで動作するため、HTTPプロトコルを期待するブラウザからのアクセスではエラーが表示されます。実際のシステムでは、セキュリティ対策も不可欠です。

関連コンテンツ

関連プログラミング言語