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

【PHP8.x】STREAM_SOCK_STREAM定数の使い方

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

作成日: 更新日:

基本的な使い方

STREAM_SOCK_STREAM定数は、PHPにおけるネットワーク通信のストリームコンテキストやソケットを作成する際に使用されるソケットタイプを表す定数です。この定数は、コネクション指向型で信頼性の高いバイトストリーム通信を指定するために利用されます。

具体的には、インターネットで広く利用されているTCP/IPプロトコルを基盤としたネットワーク通信において、データの送受信を行うためのストリームやソケットを確立する際に指定されます。例えば、クライアント側からサーバーへ接続を行うstream_socket_client()関数や、サーバー側でクライアントからの接続を待つstream_socket_server()関数などの、ネットワーク接続を扱うPHPの関数で引数として使用することが一般的です。

この定数を使用すると、送信されたデータが順序通りに、かつ欠落することなく相手に届けられることが保証される通信路が確立されます。これは、データが途中で失われたり、順序が入れ替わったりする心配が少ないため、ウェブサーバーとブラウザ間の通信や、データベースとの接続、ファイル転送など、データの完全性が非常に重要となるアプリケーションで不可欠な要素となります。信頼性が保証されないデータグラム型通信のソケットタイプであるSTREAM_SOCK_DGRAMと比較して、より高度な信頼性が要求される場面で選択されます。

構文(syntax)

1<?php
2echo STREAM_SOCK_STREAM;
3?>

引数(parameters)

引数なし

引数はありません

戻り値(return)

int

STREAM_SOCK_STREAM は、ストリームベースのソケット通信を表す定数です。この定数の値は整数で、TCP/IPのような信頼性のあるストリーム指向の通信に使用されます。

サンプルコード

PHP stream_socket_serverでTCPエコーサーバーを起動する

1<?php
2
3/**
4 * STREAM_SOCK_STREAM定数とstream_socket_server関数を用いたシンプルなTCPエコーサーバーの例。
5 *
6 * この関数は、指定されたポートでTCPサーバーを起動し、クライアントからの接続を受け入れます。
7 * 接続されたクライアントからデータを受信すると、そのデータをそのままクライアントに送り返します(エコー)。
8 * STREAM_SOCK_STREAMは、TCPストリームソケットを表す定数です。
9 * stream_socket_server関数は、デフォルトでTCPストリームソケットを作成しますが、
10 * この例ではソケットコンテキストを介してSTREAM_SOCK_STREAMを明示的に指定しています。
11 *
12 * @param string $host サーバーがリッスンするホストアドレス
13 * @param int $port サーバーがリッスンするポート番号
14 */
15function startSimpleTcpEchoServer(string $host = '0.0.0.0', int $port = 8000): void
16{
17    // サーバーアドレスを定義 (例: "tcp://0.0.0.0:8000")
18    $serverAddress = "tcp://{$host}:{$port}";
19
20    // ソケットコンテキストオプションを定義します。
21    // STREAM_SOCK_STREAMは、TCPストリームソケットのタイプを指定する定数です。
22    // stream_socket_server関数はURI "tcp://" で既にTCPソケットを認識しますが、
23    // ここではリファレンス情報に沿ってSTREAM_SOCK_STREAM定数を明示的に利用しています。
24    $contextOptions = [
25        'socket' => [
26            'type' => STREAM_SOCK_STREAM, // ソケットのタイプをTCPストリームに設定
27        ],
28    ];
29    $context = stream_context_create($contextOptions);
30
31    // ソケットサーバーを作成します。
32    // STREAM_SERVER_BIND と STREAM_SERVER_LISTEN フラグは、
33    // ソケットを指定されたアドレスにバインドし、接続を待ち受けるために必要です。
34    $server = @stream_socket_server(
35        $serverAddress,
36        $errno,
37        $errstr,
38        STREAM_SERVER_BIND | STREAM_SERVER_LISTEN,
39        $context
40    );
41
42    if (!$server) {
43        // サーバーの起動に失敗した場合のエラー処理
44        echo "エラー: サーバーを起動できませんでした。 [$errno] $errstr\n";
45        return;
46    }
47
48    echo "TCPエコーサーバーが {$serverAddress} で起動しました。Ctrl+C で終了します。\n";
49
50    // 無限ループでクライアントからの接続を待ち続けます。
51    while (true) {
52        // クライアントからの接続を受け入れます。
53        // stream_socket_accept は、新しい接続が来るまで処理をブロックします。
54        // タイムアウトを -1 に設定することで、無限に待機します。
55        $client = @stream_socket_accept($server, -1);
56
57        if ($client === false) {
58            // クライアント接続の受け入れに失敗した場合のエラー処理
59            echo "エラー: クライアント接続の受け入れに失敗しました: " . (error_get_last()['message'] ?? '不明なエラー') . "\n";
60            continue;
61        }
62
63        echo "クライアントが接続しました: " . stream_socket_get_name($client, true) . "\n";
64
65        // 接続されたクライアントからデータを読み込み、エコーバックします。
66        while (!feof($client)) {
67            $data = fread($client, 1024); // クライアントから最大1024バイト読み込み
68
69            if ($data === false || $data === '') {
70                // 読み込みエラー、またはクライアントが接続を閉じた場合にループを抜ける
71                break;
72            }
73
74            echo "受信: " . trim($data) . "\n";
75            fwrite($client, "エコー: " . $data); // 受信したデータを"エコー: "のプレフィックスを付けて送り返す
76        }
77
78        // クライアントソケットを閉じます。
79        fclose($client);
80        echo "クライアントが切断しました。\n";
81    }
82
83    // この行は、上記の無限ループのため通常到達しません。
84    // サーバーシャットダウン時に明示的にソケットを閉じる場合はここに記述します。
85    // fclose($server);
86}
87
88// サーバーを起動します。
89// 例: PHP組み込みWebサーバーのようにコマンドラインから実行します。
90// php your_script_name.php
91startSimpleTcpEchoServer();

このPHPコードは、指定したアドレスとポートで動作するシンプルなTCPエコーサーバーを構築する例です。クライアントからデータを受信すると、それをそのままクライアントに送り返します。

核となるのは、サーバーソケットを作成し、クライアントからの接続を待ち受けるstream_socket_server関数です。この関数は、URIスキーム(例: tcp://)からソケットタイプを推測できますが、STREAM_SOCK_STREAM定数を明示的に指定することで、TCPストリームソケットであることを明確にしています。STREAM_SOCK_STREAMは、TCPプロトコルで使用される、データの順序と信頼性が保証された「ストリーム型」のソケットを表す整数値で、引数はなく、戻り値は整数型です。

サーバーソケットの作成時には、STREAM_SERVER_BINDSTREAM_SERVER_LISTENフラグを組み合わせて使用し、指定したアドレスにソケットを紐付け、接続待機状態にします。サーバーが起動すると、stream_socket_accept関数でクライアントからの接続を受け入れ、接続があるまで処理を一時停止します。クライアントが接続すると、fread関数でデータを受信し、fwrite関数で受信データを加工してクライアントに送り返します。通信が完了すると、fclose関数でクライアントとの接続を閉じ、次の接続を待ちます。このコードは、基本的なネットワーク通信処理の仕組みを学ぶのに役立ちます。

STREAM_SOCK_STREAMはTCPストリームソケットを示す定数ですが、stream_socket_server関数でURIにtcp://を指定する場合、この定数をソケットコンテキストで明示的に指定しなくてもTCPソケットは作成されます。このサンプルはリファレンス情報に合わせて定数を明示的に利用しています。

@演算子によるエラー抑制は学習目的であり、実際のシステムではエラーメッセージを適切に記録し、例外処理を実装することが重要です。このサーバーは無限ループで動作するため、プログラムを終了するにはCtrl+Cなどの強制終了が必要です。Graceful Shutdown(正常終了処理)の実装は別途考慮してください。stream_socket_acceptfreadは新しい接続やデータが来るまで処理を停止(ブロック)するため、多数の同時接続を扱う場合はノンブロッキングI/Oやイベントループの利用を検討してください。実運用では認証やSSL/TLSによる暗号化など、セキュリティ対策が必須です。

PHPでstream_socket_acceptを使い接続を処理する

1<?php
2
3/**
4 * PHPエコーサーバーを起動し、クライアントからの接続を処理します。
5 * システムエンジニアを目指す初心者向けに、stream_socket_accept の基本的な使い方を示します。
6 */
7function runEchoServer(): void
8{
9    // この定数 STREAM_SOCK_STREAM は、TCPのような、
10    // データの流れがストリーム(連続的)であるソケットタイプを示します。
11    // stream_socket_server() で 'tcp://' スキームを使用すると、
12    // 内部的にこのタイプのソケットが作成され、ストリーム通信が可能になります。
13    // 通常、高レベルなストリーム関数では直接指定する必要はありません。
14
15    $address = 'tcp://127.0.0.1:8000'; // サーバーがリッスンするアドレスとポート
16
17    // stream_socket_server() はサーバーソケットを作成し、指定されたアドレスで接続を待ち受けます。
18    // STREAM_SERVER_BIND はアドレスにバインドすることを、
19    // STREAM_SERVER_LISTEN は接続待ちを開始することを示します。
20    $server = stream_socket_server($address, $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN);
21
22    if (!$server) {
23        error_log("サーバーの起動に失敗しました: {$errstr} ({$errno})");
24        exit(1); // エラー発生時はプログラムを終了
25    }
26
27    echo "PHPエコーサーバーが {$address} でリッスンを開始しました。Ctrl+Cで停止します。\n";
28
29    // 無限ループでクライアントからの接続を待ち続けます
30    while (true) {
31        // stream_socket_accept() は、サーバーソケット ($server) 上で
32        // クライアントからの新しい接続を待ち、接続があればそのクライアントとの
33        // 新しいソケットリソースを返します。接続がない間は処理をブロックします。
34        echo "クライアントの接続を待機中...\n";
35        $client = stream_socket_accept($server);
36
37        if ($client) {
38            echo "クライアントが接続しました。\n";
39
40            // クライアントから最大1024バイトのデータを読み込む
41            $message = fread($client, 1024);
42            $message = trim($message); // 受信データ前後の空白を除去
43
44            echo "受信: '{$message}'\n";
45
46            // 受信したメッセージをクライアントにそのまま返信する (エコー)
47            $response = "サーバーからの返信: あなたは '{$message}' と送りました。\n";
48            fwrite($client, $response);
49
50            // クライアントとの接続を閉じる
51            fclose($client);
52            echo "クライアント接続を閉じました。\n";
53        } else {
54            // stream_socket_accept が false を返した場合(エラーなど)
55            error_log("stream_socket_accept() で問題が発生しました。");
56            // エラーが発生してもサーバーは停止せず、次の接続を待ちます
57        }
58    }
59
60    // サーバーソケットを閉じる(この例では無限ループのため、通常は到達しません)
61    // fclose($server);
62}
63
64// サーバーを実行
65runEchoServer();

このサンプルコードは、PHPを用いて簡単なエコーサーバーを構築し、クライアントからの接続を処理する基本的な流れを示しています。

STREAM_SOCK_STREAMは、TCPプロトコルに代表されるように、データが連続的な流れ(ストリーム)として扱われるソケット通信のタイプを示す整数定数です。stream_socket_server()関数で'tcp://'のようなスキームを使う場合、このストリームタイプのソケットが内部的に利用され、データの連続性を保証した通信が可能になります。通常、高レベルな関数を使用する際には直接この定数を指定する必要はありませんが、通信の基盤を理解する上で重要な概念です。

stream_socket_accept()関数は、サーバーソケット上でクライアントからの新しい接続を待ち受けるために使われます。引数には、stream_socket_server()で作成されたサーバーソケットリソースを指定します。この関数は、クライアントからの接続要求があるまで処理を一時停止(ブロック)し、接続が確立されると、そのクライアントとの個別の通信に利用する新しいソケットリソースを返します。これにより、サーバーはクライアントとデータの送受信が可能になります。接続に失敗した場合はfalseを戻り値として返します。このサンプルでは、接続したクライアントから受信したメッセージをそのまま返信し、通信終了後に接続を閉じる一連の流れを実装しています。

STREAM_SOCK_STREAM定数はTCPのようなストリーム通信に使われるソケットタイプを示し、サンプルではtcp://スキームでstream_socket_serverを利用すると内部的にこのタイプが使われています。stream_socket_accept()はクライアント接続があるまで処理をブロックして待ちます。複数のクライアントを同時に処理したい場合は、非ブロッキングモードやstream_select()などの非同期処理、またはマルチプロセス/スレッド化が必要です。ネットワーク処理では予期せぬエラーが頻発するため、本コードは基本的なエラーログのみですが、実運用ではより詳細なエラーハンドリングやリトライ機構が求められます。クライアント接続後のfclose($client)によるリソース解放は重要です。サーバー全体の停止時にはfclose($server)でサーバーソケットも閉じるように実装してください。このサンプルは基本的な動作を示すものであり、実際のシステムでは認証、暗号化、入力検証などのセキュリティ対策が必須です。

関連コンテンツ

関連IT用語

関連プログラミング言語