【PHP8.x】stream_socket_get_name()関数の使い方
stream_socket_get_name関数の使い方について、初心者にもわかりやすく解説します。
基本的な使い方
stream_socket_get_name関数は、PHPで確立されたネットワーク接続(ソケットストリーム)に関する情報を取得する関数です。この関数を使用することで、プログラムが現在やり取りしている相手のIPアドレスとポート番号、あるいは自身が使用しているIPアドレスとポート番号を確認できます。
具体的には、第一引数にstream_socket_clientやstream_socket_serverなどの関数で作成されたソケットストリームのリソースを指定します。第二引数には真偽値trueまたはfalseを設定します。trueを指定すると接続相手である「リモート側」のIPアドレスとポート番号が取得され、falseを指定すると自身である「ローカル側」のIPアドレスとポート番号が取得されます。
成功した場合、この関数は「IPアドレス:ポート番号」という形式の文字列を返します。たとえば、「192.168.1.100:8080」のような形式で情報が提供されます。もし何らかの理由で情報が取得できなかったり、エラーが発生したりした場合にはfalseが返されます。
この関数は、ネットワークアプリケーションのデバッグ時や、接続に関するログを記録したい場合、または接続しているクライアントやサーバーの情報をプログラム内で識別する必要がある場合に非常に便利です。ネットワーク通信の詳細を把握するために利用されます。
構文(syntax)
1<?php 2$socket = stream_socket_server("tcp://127.0.0.1:0", $errno, $errstr); 3if (!$socket) { 4 echo "$errstr ($errno)\n"; 5} else { 6 $name = stream_socket_get_name($socket, false); 7 echo "Socket name: " . $name . "\n"; 8 fclose($socket); 9} 10?>
引数(parameters)
resource $socket, bool $remote
- resource $socket: 名前を取得したいソケットリソースを指定します。
- bool $remote: trueを指定するとリモートアドレス(接続先)、falseを指定するとローカルアドレス(接続元)の名前を取得します。
戻り値(return)
string|false
指定されたストリームソケットに関連付けられたローカルまたはリモートの名前(IPアドレスとポート番号)を文字列で返します。失敗した場合はfalseを返します。
サンプルコード
PHPでTCPサーバーとアドレス情報を取得する
1<?php 2 3/** 4 * PHPのストリームソケットサーバーとアドレス情報取得のサンプル。 5 * 6 * stream_socket_server を使用してTCPサーバーを起動し、 7 * stream_socket_get_name で接続のアドレス情報を取得する方法を示します。 8 * 9 * 実行方法: 10 * 1. ターミナルで `php your_script_name.php` を実行し、サーバーを起動します。 11 * 2. 別のターミナルで `telnet 127.0.0.1 8000` または `nc 127.0.0.1 8000` を実行して接続します。 12 * 3. サーバー側とクライアント側でアドレス情報が表示され、簡単なメッセージを送受信できます。 13 */ 14function runStreamSocketExample(): void 15{ 16 // サーバーがリッスンするIPアドレスとポート番号を設定 17 $host = '127.0.0.1'; 18 $port = 8000; 19 $serverAddress = "tcp://{$host}:{$port}"; 20 21 echo "TCPサーバーを起動中: {$serverAddress}\n"; 22 echo "クライアントからの接続を待機しています...\n"; 23 24 // stream_socket_server を使用してサーバーソケットを作成します。 25 // 第1引数: サーバーのアドレス。例: 'tcp://127.0.0.1:8000' 26 // 第2引数: エラー番号が格納される変数への参照。 27 // 第3引数: エラーメッセージが格納される変数への参照。 28 // 第4引数: ソケットの動作オプション。 29 // STREAM_SERVER_BIND: 指定されたアドレスにソケットをバインドします。 30 // STREAM_SERVER_LISTEN: 接続をリッスン状態にします。 31 $serverSocket = stream_socket_server( 32 $serverAddress, 33 $errno, 34 $errstr, 35 STREAM_SERVER_BIND | STREAM_SERVER_LISTEN 36 ); 37 38 // ソケット作成に失敗した場合の処理 39 if (false === $serverSocket) { 40 die("サーバーソケットの作成に失敗しました: {$errstr} ({$errno})\n"); 41 } 42 43 // サーバーソケット自身のローカルアドレスを取得します。 44 // stream_socket_get_name の第2引数に false を指定すると、 45 // そのソケットのローカルアドレス(自身のアドレス)を返します。 46 $serverLocalName = stream_socket_get_name($serverSocket, false); 47 if ($serverLocalName === false) { 48 echo "警告: サーバーソケットのローカルアドレス取得に失敗しました。\n"; 49 } else { 50 echo "サーバーのローカルアドレス (リッスンしているアドレス): {$serverLocalName}\n"; 51 } 52 53 // stream_socket_accept を使用して、クライアントからの接続を待機し、受け入れます。 54 // 第2引数に -1 を指定すると、接続があるまで無期限に待機します。 55 $clientSocket = stream_socket_accept($serverSocket, -1); 56 57 // クライアント接続の受け入れに失敗した場合の処理 58 if (false === $clientSocket) { 59 echo "クライアント接続の受け入れに失敗しました。\n"; 60 fclose($serverSocket); // サーバーソケットを閉じる 61 return; 62 } 63 64 echo "クライアントが接続しました!\n"; 65 66 // 接続してきたクライアントソケットのローカルアドレス (サーバー側) を取得します。 67 // これはサーバーがクライアント接続を受け入れた際に使用しているサーバー側のIP:ポートです。 68 // クライアントソケットから見ると、これは接続先のサーバーのアドレスになります。 69 $clientConnectionLocalName = stream_socket_get_name($clientSocket, false); 70 if ($clientConnectionLocalName === false) { 71 echo "警告: クライアント接続のローカルアドレス取得に失敗しました。\n"; 72 } else { 73 echo "クライアント接続のサーバー側アドレス: {$clientConnectionLocalName}\n"; 74 } 75 76 // 接続してきたクライアントソケットのリモートアドレス (クライアント自身) を取得します。 77 // stream_socket_get_name の第2引数に true を指定すると、 78 // そのソケットが接続しているリモートピアのアドレスを返します。 79 // この場合、クライアントソケットから見たリモートピアは、接続してきたクライアント自身です。 80 $clientRemoteName = stream_socket_get_name($clientSocket, true); 81 if ($clientRemoteName === false) { 82 echo "警告: クライアントのリモートアドレス取得に失敗しました。\n"; 83 } else { 84 echo "クライアントのリモートアドレス: {$clientRemoteName}\n"; 85 } 86 87 // クライアントからのデータを受信します。 88 // fread は指定されたバイト数(ここでは1024)をストリームから読み込みます。 89 $message = fread($clientSocket, 1024); 90 if ($message === false) { 91 echo "クライアントからの読み込みに失敗しました。\n"; 92 } else { 93 echo "クライアントから受信: " . trim($message) . "\n"; 94 } 95 96 // クライアントに応答を送信します。 97 $response = "Hello from PHP server! Your address is {$clientRemoteName}\n"; 98 fwrite($clientSocket, $response); 99 echo "クライアントに応答を送信しました。\n"; 100 101 // 処理後、クライアントソケットを閉じます。 102 fclose($clientSocket); 103 echo "クライアントソケットを閉じました。\n"; 104 105 // 処理後、サーバーソケットを閉じます。 106 fclose($serverSocket); 107 echo "サーバーソケットを閉じました。\n"; 108 echo "サーバーはシャットダウンしました。\n"; 109} 110 111// このスクリプトがコマンドラインインターフェース (CLI) から直接実行された場合にのみ、 112// runStreamSocketExample 関数を呼び出します。 113if (php_sapi_name() === 'cli') { 114 runStreamSocketExample(); 115}
このサンプルコードは、PHPでTCPサーバーを構築し、クライアントとの接続におけるアドレス情報をstream_socket_get_name関数で取得する方法を初心者向けに示しています。
まず、stream_socket_server関数を使って指定されたIPアドレスとポートでTCPサーバーを起動し、クライアントからの接続を待ち受けます。サーバーソケットの作成に成功すると、そのソケット自身のローカルアドレス(サーバーが待ち受けているアドレス)をstream_socket_get_nameの第2引数にfalseを指定して取得します。
クライアントが接続すると、stream_socket_accept関数が接続を受け入れ、クライアントとの通信に使う新しいソケットが生成されます。このクライアントソケットに対し、stream_socket_get_nameの第2引数にfalseを指定すると、サーバー側がクライアントとの通信に使用しているローカルアドレス(サーバーのアドレス)が取得できます。一方、第2引数にtrueを指定すると、接続してきたクライアントのリモートアドレス(クライアント自身のアドレス)が取得されます。stream_socket_get_nameは、第1引数にソケットリソース、第2引数にローカルかリモートかを示す真偽値を受け取り、成功時にはIPアドレス:ポート形式の文字列を、失敗時にはfalseを返します。
その後、freadでクライアントからのメッセージを受信し、fwriteで応答を送信する簡単な通信が行われ、最後にソケットが閉じられます。このコードを通じて、ソケット通信とstream_socket_get_nameによるアドレス情報の取得の基本を学ぶことができます。
ソケットは利用後に必ずfclose関数で閉じ、リソースリークやポート占有を防いでください。stream_socket_serverやstream_socket_acceptなど、ソケット関連の関数は失敗時にfalseを返すため、必ず戻り値をチェックし、エラー処理を適切に行ってください。stream_socket_get_name関数の第2引数$remoteは、trueを指定すると接続相手のアドレス、falseを指定するとソケット自身のローカルアドレスを取得します。この違いを理解して使い分けてください。このサンプルは学習用であり、実際のシステムでは認証や暗号化などのセキュリティ対策を別途実装する必要があります。
PHP: stream_socket_client で接続し socket 名を取得する
1<?php 2 3/** 4 * stream_socket_client を使用してリモートサーバーにTCP接続を確立し、 5 * stream_socket_get_name でその接続のローカルおよびリモートのソケット名(IPアドレスとポート)を 6 * 取得して表示するサンプルコードです。 7 * 8 * このコードは、指定されたリモートホストとポートに接続を試みます。 9 * 接続が成功すると、自身のIPアドレスとポート、および接続先サーバーのIPアドレスとポートを表示します。 10 * 11 * システムエンジニアを目指す初心者の方へ: 12 * - stream_socket_client は、ネットワーク上の他のコンピュータ(サーバー)に接続するための「ドア」を開くイメージです。 13 * - stream_socket_get_name は、その開いたドアが、自分からはどう見え(ローカル)、相手からはどう見えているか(リモート)、 14 * つまり、それぞれの側のアドレス(IPアドレスとポート番号)を確認するのに使います。 15 */ 16 17// 接続先のホストとポートを定義します。 18// 例としてGoogleのWebサーバー (HTTPポート 80) を使用しますが、 19// ネットワーク環境によっては接続できない場合があります。 20// ローカルでテストする場合: 21// 1. ターミナルで `php -S 127.0.0.1:8000` と実行し、簡易HTTPサーバーを起動します。 22// 2. 以下の $host を '127.0.0.1'、 $port を 8000 に設定してください。 23$host = 'www.google.com'; 24$port = 80; 25// 接続アドレスの形式は "tcp://ホスト名:ポート番号" です。 26$address = "tcp://{$host}:{$port}"; 27 28echo "接続先: {$address}" . PHP_EOL; 29echo "リモートサーバーへの接続を試みます..." . PHP_EOL; 30 31// stream_socket_client 関数を使用してリモートサーバーに接続を試みます。 32// 第1引数: 接続先アドレス 33// 第2引数: エラーコードを格納する変数 (参照渡し) 34// 第3引数: エラーメッセージを格納する変数 (参照渡し) 35// 第4引数: 接続タイムアウト時間 (秒) 36$socket = stream_socket_client($address, $errno, $errstr, 30); 37 38if (!$socket) { 39 // 接続に失敗した場合の処理 40 echo "ERROR: 接続失敗 - {$errstr} ({$errno})" . PHP_EOL; 41} else { 42 // 接続に成功した場合の処理 43 echo "接続に成功しました!" . PHP_EOL; 44 45 // stream_socket_get_name を使用して、自身のソケット名(ローカル側)を取得します。 46 // 第2引数が `false` の場合、ローカルの接続情報を返します。 47 $local_name = stream_socket_get_name($socket, false); 48 if ($local_name !== false) { 49 echo "ローカルソケット名 (自身のIP:ポート): {$local_name}" . PHP_EOL; 50 } else { 51 echo "ローカルソケット名の取得に失敗しました。" . PHP_EOL; 52 } 53 54 // stream_socket_get_name を使用して、接続先サーバーのソケット名(リモート側)を取得します。 55 // 第2引数が `true` の場合、リモート(接続先)の接続情報を返します。 56 $remote_name = stream_socket_get_name($socket, true); 57 if ($remote_name !== false) { 58 echo "リモートソケット名 (接続先のIP:ポート): {$remote_name}" . PHP_EOL; 59 } else { 60 echo "リモートソケット名の取得に失敗しました。" . PHP_EOL; 61 } 62 63 // 確立したソケット接続を閉じます。 64 fclose($socket); 65 echo "接続を閉じました。" . PHP_EOL; 66} 67 68?>
stream_socket_get_name関数は、ネットワークソケットの接続情報を取得するために使用されます。この関数は、stream_socket_clientなどで確立されたネットワーク接続のリソース($socket引数)を受け取ります。第二引数$remoteにtrueを指定すると接続相手(リモート)のIPアドレスとポート番号を、falseを指定すると自身のIPアドレスとポート番号(ローカル)を返します。取得に成功すると「IPアドレス:ポート番号」形式の文字列を返し、失敗した場合はfalseを返します。
このサンプルコードでは、まずstream_socket_client関数を使用して指定されたリモートサーバーへTCP接続を試みます。接続が成功した場合、stream_socket_get_name関数を二度呼び出します。一度目は$remote引数にfalseを渡し、自身のプログラムの接続情報を取得して表示します。二度目はtrueを渡し、接続先サーバーのリモート情報を取得して表示しています。これにより、自身のプログラムがネットワーク上でどのように接続されているか、また接続先の情報も具体的に確認できます。接続に失敗した場合はエラーメッセージが表示され、成功した場合は接続を閉じる処理を行います。
stream_socket_client関数は、ネットワーク環境や設定によっては接続に失敗する可能性があるため、必ずエラー処理を行い、エラーメッセージを確認するようにしてください。接続先のアドレスは、tcp://ホスト名:ポート番号という形式で正確に指定する必要があります。stream_socket_get_name関数は、成功時には接続情報を示す文字列を、失敗時にはfalseを返すため、戻り値がfalseでないか常に確認し、適切に分岐処理を行うことが重要です。また、この関数の第二引数がtrueの場合には接続先のリモート情報を、falseの場合には自身のローカル情報を取得するという違いを明確に理解してください。ネットワーク接続を確立した後は、必ずfclose関数を使用してソケットリソースを適切に解放し、リソースリークを防ぐことが安全なプログラミングの基本となります。ファイアウォールなどのセキュリティ設定により、意図した接続がブロックされる場合があることにも留意が必要です。