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

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

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

作成日: 更新日:

基本的な使い方

STREAM_IPPROTO_UDP定数は、UDP (User Datagram Protocol) プロトコルを表す定数です。PHPでネットワーク通信を扱うストリーム機能やソケット通信において、基盤となるIPプロトコルとしてUDPを指定したい場合に使用されます。

具体的には、stream_context_create関数などを用いてストリームコンテキストを作成する際に、socketトランスポートのオプションとして、IPプロトコルをUDPに設定するためにこの定数が活用されます。例えば、'socket'のキーを持つ配列内で'ip_proto' => STREAM_IPPROTO_UDPのように指定することで、そのストリームがUDPを利用した通信を行うよう設定できます。

UDPは、データの送受信に際してコネクション(接続)の確立が不要な、コネクションレス型のプロトコルです。そのため、TCPのようなデータの信頼性や順序保証よりも、通信速度やリアルタイム性が重視される用途に適しています。例えば、ライブストリーミング、オンラインゲームの一部、DNSクエリなど、多少のデータ損失が発生しても通信の遅延を避けたい場面で利用されることがあります。

この定数を用いることで、開発者はPHPのストリームAPIを通じて、UDPプロトコルの特性を活かしたネットワークアプリケーションを構築し、特定の通信要件に応じた柔軟なプログラミングが可能になります。

構文(syntax)

1<?php
2echo STREAM_IPPROTO_UDP;

引数(parameters)

引数なし

引数はありません

戻り値(return)

戻り値なし

戻り値はありません

サンプルコード

PHPによるUDPエコーサーバーを実装する

1<?php
2
3/**
4 * UDPエコーサーバーを起動し、クライアントからのメッセージを待ち受け、
5 * 受信したメッセージをそのまま返信(エコーバック)します。
6 */
7function runUdpEchoServer(): void
8{
9    // サーバーが待ち受けるアドレスとポートを指定します。
10    // 'udp://' スキームは、UDPプロトコルを使用することを意味します。
11    // STREAM_IPPROTO_UDP はUDPプロトコルを表す定数ですが、
12    // stream_socket_server では URIスキームでプロトコルを指定するのが一般的です。
13    // この定数は、より低レベルなソケット操作 (例: socket_create) で
14    // 明示的にプロトコル番号を指定する際に使用されます。
15    const SERVER_ADDRESS = 'udp://127.0.0.1:12345';
16    // 受信するメッセージの最大サイズをバイト単位で指定します。
17    const MAX_MESSAGE_SIZE = 1024;
18
19    // UDPサーバーソケットを作成します。
20    // 第1引数: サーバーアドレス (URI形式)
21    // 第2引数: エラー番号が格納される変数への参照 (失敗した場合)
22    // 第3引数: エラーメッセージが格納される変数への参照 (失敗した場合)
23    $serverSocket = stream_socket_server(SERVER_ADDRESS, $errno, $errstr);
24
25    if (false === $serverSocket) {
26        // ソケット作成に失敗した場合のエラー処理
27        echo "エラー: サーバーソケットを作成できませんでした ($errno) $errstr\n";
28        return;
29    }
30
31    echo "UDPエコーサーバーが " . SERVER_ADDRESS . " で起動しました。\n";
32    echo "クライアントからのメッセージを待機しています... (Ctrl+Cで終了)\n";
33
34    // 無限ループでクライアントからのメッセージを待ち受けます。
35    while (true) {
36        // クライアントからのデータを受信します。
37        // stream_socket_recvfrom は、受信したデータと送信元アドレスを返します。
38        // 第1引数: ソケットリソース
39        // 第2引数: 受信可能な最大バイト数
40        // 第3引数: フラグ (通常は0)
41        // 第4引数: 送信元アドレスが格納される変数への参照
42        $message = stream_socket_recvfrom($serverSocket, MAX_MESSAGE_SIZE, 0, $peerName);
43
44        if (false === $message) {
45            // メッセージ受信エラー
46            echo "エラー: メッセージの受信に失敗しました。\n";
47            continue; // 次のメッセージを待機
48        }
49
50        // 受信したメッセージと送信元情報を表示します。
51        $trimmedMessage = trim($message); // 改行などを除去して表示
52        echo "受信 ('{$peerName}'): {$trimmedMessage}\n";
53
54        // 受信したメッセージをそのままクライアントに返信(エコーバック)します。
55        // stream_socket_sendto は、指定したアドレスへデータを送信します。
56        // 第1引数: ソケットリソース
57        // 第2引数: 送信するデータ
58        // 第3引数: フラグ (通常は0)
59        // 第4引数: 送信先アドレス (受信したクライアントのアドレス)
60        $bytesSent = stream_socket_sendto($serverSocket, $message, 0, $peerName);
61
62        if (false === $bytesSent) {
63            // メッセージ送信エラー
64            echo "エラー: メッセージの送信に失敗しました ('{$peerName}').\n";
65        } else {
66            echo "送信 ('{$peerName}'): {$trimmedMessage} ({$bytesSent} バイト)\n";
67        }
68    }
69
70    // この行は無限ループのため通常到達しませんが、リソース解放の習慣として記載。
71    fclose($serverSocket);
72}
73
74// サーバーを起動する関数を実行します。
75runUdpEchoServer();

このPHPコードは、UDPプロトコルを用いたエコーサーバーの起動方法を示しています。クライアントから受信したメッセージをそのまま返信する機能を持っています。

まず、stream_socket_server関数を用いてサーバーソケットを作成します。この関数は、指定されたアドレスとポートでクライアントからの接続を待ち受けるためのソケットリソースを返します。第一引数には'udp://127.0.0.1:12345'のようにURI形式でプロトコルとアドレスを指定し、第二・第三引数にはエラー発生時に情報が格納される変数を参照渡しします。ソケットの作成に失敗した場合はfalseを返します。

STREAM_IPPROTO_UDPはUDPプロトコルを表す定数ですが、stream_socket_server関数ではURIスキーム(udp://)でプロトコルを指定するのが一般的なため、このサンプルコードでは直接使用されていません。この定数は、より低レベルなsocket_createのような関数でプロトコル番号を明示的に指定する際に利用されます。

サーバーは無限ループに入り、stream_socket_recvfrom関数を使ってクライアントからのメッセージを待ち受けます。この関数は、ソケットリソース、受信可能な最大バイト数などを引数に取り、受信したデータと送信元クライアントのアドレスを返します。メッセージを受信すると、stream_socket_sendto関数を用いて、受信したデータをそのまま送信元クライアントへ返信(エコーバック)します。この関数は、ソケットリソース、送信データ、送信先アドレスを引数に取ります。この一連の処理により、PHPでUDP通信の基本的なサーバーを構築する流れを理解できます。

STREAM_IPPROTO_UDPは、socket_createのような低レベルなソケット関数でUDPプロトコルを明示的に指定する際に使用する定数です。今回のサンプルコードのようにstream_socket_server関数でURIスキーム(udp://)を用いる場合、この定数を直接指定する必要はありません。本コードはUDPサーバーの基本的な動作を示しており、UDPがコネクションレスであるため、メッセージの到達や順序が保証されない点を理解しておくことが重要です。また、サーバーは無限ループで動作するため、手動で停止(Ctrl+Cなど)させる必要があります。運用時には、エラー処理の強化やGraceful Shutdown(正常な終了処理)を考慮することが大切です。

PHPでSTREAM_IPPROTO_UDPを使ったUDPクライアントを作る

1<?php
2
3/**
4 * STREAM_IPPROTO_UDP 定数を使用して UDP クライアントソケットを作成し、メッセージを送信する。
5 *
6 * この関数は、PHP のストリームソケットAPIを使ってUDP通信を行う方法を、
7 * システムエンジニアを目指す初心者にも分かりやすく示すことを目的としています。
8 * STREAM_IPPROTO_UDP 定数を stream_context_create の 'ip_protocol' オプションに指定することで、
9 * IPプロトコルとしてUDPを明示的に使用するソケットを作成します。
10 *
11 * @param string $host 送信先のホスト名またはIPアドレス (例: '127.0.0.1')
12 * @param int $port 送信先のポート番号 (例: 12345)
13 * @param string $message 送信するデータ文字列
14 * @return bool メッセージの送信が成功した場合は true、それ以外は false
15 */
16function sendUdpMessage(string $host, int $port, string $message): bool
17{
18    // UDP通信のためのソケットコンテキストを作成します。
19    // 'ip_protocol' オプションに STREAM_IPPROTO_UDP を指定することで、
20    // 使用するIPプロトコルがUDPであることを明示的に宣言します。
21    $context = stream_context_create([
22        'socket' => [
23            'ip_protocol' => STREAM_IPPROTO_UDP,
24        ],
25    ]);
26
27    $errno = null;  // エラーコードを格納する変数
28    $errstr = null; // エラーメッセージを格納する変数
29
30    // stream_socket_client() 関数を使用して UDP クライアントソケットを開きます。
31    // "udp://" スキームは、プロトコルとしてUDPを使用することを示します。
32    // STREAM_CLIENT_CONNECT フラグは、このソケットがデフォルトの送信先を持つことを意味し、
33    // 後続のデータ送信時に宛先を再度指定する必要がなくなります。
34    $socket = stream_socket_client(
35        "udp://{$host}:{$port}",
36        $errno,
37        $errstr,
38        3, // ソケット接続のタイムアウトを3秒に設定
39        STREAM_CLIENT_CONNECT,
40        $context
41    );
42
43    // ソケットの作成が失敗した場合は、エラーメッセージを表示して処理を終了します。
44    if (!$socket) {
45        echo "エラー: ソケットの作成に失敗しました ($errno): $errstr\n";
46        return false;
47    }
48
49    echo "UDPソケットが正常に作成されました。宛先: {$host}:{$port}\n";
50
51    // メッセージを送信します。
52    // UDP (User Datagram Protocol) はコネクションレスで信頼性の低いプロトコルです。
53    // メッセージが相手に到達したことや、順序が保証されることはありません。
54    $bytesWritten = stream_socket_sendto($socket, $message);
55
56    // 送信結果を確認します。
57    if ($bytesWritten === false) {
58        echo "エラー: メッセージの送信に失敗しました。\n";
59        // ソケットが開いている場合は閉じます
60        fclose($socket);
61        return false;
62    }
63
64    echo "メッセージ '{$message}' を送信しました ({$bytesWritten} バイト)。\n";
65
66    // 使用後のソケットは閉じます。
67    fclose($socket);
68    echo "ソケットを閉じました。\n";
69
70    return true;
71}
72
73// このサンプルコードを単体で実行するために、具体的な送信先とメッセージを指定します。
74// 実際の環境でメッセージが受信されることを確認するには、
75// 指定したポートでUDPメッセージをリッスンするサーバープロセスが別途必要です。
76$targetHost = '127.0.0.1'; // ローカルホストを指すIPアドレス
77$targetPort = 12345;       // 受信側がリッスンしている可能性のあるポート
78$messageToSend = 'Hello from PHP UDP Client!';
79
80// 関数を呼び出してメッセージを送信します。
81sendUdpMessage($targetHost, $targetPort, $messageToSend);

このサンプルコードは、PHPでUDPクライアントソケットを作成し、指定されたホストとポートへメッセージを送信する方法を解説しています。中心となるのはSTREAM_IPPROTO_UDP定数で、これはIPプロトコルとしてUDP(User Datagram Protocol)を明示的に指定するために使用されます。

sendUdpMessage関数では、まずstream_context_create関数を使ってソケットコンテキストを作成し、その設定で'ip_protocol'オプションにSTREAM_IPPROTO_UDPを指定します。これにより、作成されるソケットがUDPプロトコルを使用することが宣言されます。次に、stream_socket_client関数で実際のUDPソケットを開きます。この際、"udp://"というプレフィックスを付けてプロトコルがUDPであることを示し、引数として送信先の$host(ホスト名またはIPアドレス)と$port(ポート番号)を渡します。STREAM_CLIENT_CONNECTフラグは、ソケットが指定された宛先へデフォルトで送信する設定であることを意味します。

ソケットが正常に作成された後、stream_socket_sendto関数で引数として渡された$messageを送信します。UDPはコネクションレスで、メッセージの到達や順序が保証されないプロトコルである点に注意が必要です。sendUdpMessage関数は、メッセージの送信が成功した場合はtrueを、失敗した場合はfalseを戻り値として返します。最後に、使用後のソケットはfclose関数で適切に閉じる必要があります。

このサンプルコードはUDP通信の基本的な流れを示していますが、UDPはコネクションレスであり、送信したメッセージが必ず相手に到達することや、送った順序が保証されるわけではありません。そのため、重要なデータをやり取りする場合は、到達確認などの仕組みを自身で実装する必要があります。また、送信したメッセージを受け取るためには、指定したポートでUDP通信をリッスンするサーバープロセスが別途必要です。ソケットの作成失敗時のエラーチェックや、処理終了時に必ずfcloseでソケットを閉じることは、リソースの適切な管理のために非常に重要です。ファイアウォールの設定によって通信がブロックされる可能性もあるため、動作しない場合は確認してください。

関連コンテンツ

関連IT用語

関連プログラミング言語