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

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

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

作成日: 更新日:

基本的な使い方

stream_socket_client関数は、指定されたネットワークアドレスに対してクライアント側のソケット接続を開始する関数です。この関数は、Webサーバーやデータベースサーバー、あるいはその他のネットワークサービスなど、外部のサーバーと通信を行いたい場合に利用されます。

具体的には、接続先のアドレス(例: tcp://example.com:80unix:///tmp/mysocket.sock のようなプロトコル、ホスト、ポート番号を含む形式)を第一引数に指定することで、そのアドレスへの接続を試みます。接続に成功すると、データの読み書きが可能なストリームリソースを返します。このリソースを使用して、接続先のサーバーとデータを送受信することができます。

第二引数と第三引数には、参照渡しでエラーコードとエラーメッセージを受け取ることができ、接続に失敗した際の具体的な原因を把握するのに役立ちます。第四引数では、接続を確立するまでのタイムアウト時間を秒単位で設定することが可能です。また、第五引数のフラグを用いることで、非同期接続(接続が完了するのを待たずに処理を続行する)のような特別な挙動を指定することもできます。

この関数は、PHPで低レベルなネットワーク通信を実装する際の基本的な構成要素であり、外部サービスとの連携やカスタムプロトコルを用いた通信など、幅広いネットワークプログラミングの場面で活用されます。接続が確立できない場合はfalseを返すため、戻り値を確認してエラーハンドリングを行うことが重要です。

構文(syntax)

1stream_socket_client(
2    string $address,
3    int &$error_code = null,
4    string &$error_message = null,
5    ?float $timeout = null,
6    int $flags = STREAM_CLIENT_CONNECT,
7    ?resource $context = null
8): resource|false

引数(parameters)

string $address, ?int &$error_code = null, ?string &$error_message = null, ?float $timeout = null, int $flags = 4, ?resource $context = null

  • string $address: 接続先のネットワークアドレスを指定します。例: "tcp://example.com:80", "udp://192.168.1.100:1234"
  • ?int &$error_code = null: エラー発生時にエラーコードが格納される変数への参照です。
  • ?string &$error_message = null: エラー発生時にエラーメッセージが格納される変数への参照です。
  • ?float $timeout = null: 接続試行のタイムアウト時間を秒単位で指定します。
  • int $flags = 4: ソケットの動作を変更するためのフラグを指定します。デフォルトはSTREAM_CLIENT_CONNECT | STREAM_CLIENT_NONBLOCK です。
  • ?resource $context = null: ストリームコンテキストを指定します。

戻り値(return)

resource|false

ストリームソケットクライアント接続が成功した場合、その接続を表すリソースを返します。接続に失敗した場合は false を返します。

サンプルコード

PHP stream_socket_client でTCP接続しデータ送受信する

1<?php
2
3/**
4 * stream_socket_client のサンプルコード
5 */
6function streamSocketClientExample(string $address): void
7{
8    // タイムアウト時間を設定 (秒)
9    $timeout = 5;
10
11    // ソケット接続を試みる
12    $stream = stream_socket_client(
13        $address,
14        $errno,
15        $errstr,
16        $timeout
17    );
18
19    // エラーが発生した場合
20    if (!$stream) {
21        echo "Error: $errstr ($errno)" . PHP_EOL;
22        return;
23    }
24
25    // ソケットが正常に接続された場合
26    echo "Successfully connected to $address" . PHP_EOL;
27
28    // データを送信 (HTTP GET リクエストの例)
29    $request = "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n";
30    fwrite($stream, $request);
31
32    // 応答を読み込む
33    while (!feof($stream)) {
34        echo fgets($stream);
35    }
36
37    // ストリームを閉じる
38    fclose($stream);
39}
40
41// example.comの80番ポートに接続する例
42streamSocketClientExample("tcp://example.com:80");
43
44?>

stream_socket_client関数は、指定されたアドレスへのソケット接続を確立するために使用されます。この関数は、システムエンジニアを目指す初心者にとって、ネットワークプログラミングの基礎を理解する上で重要な役割を果たします。

$address引数には、接続先のソケットアドレスを指定します。例えば、"tcp://example.com:80" のように、プロトコル、ホスト名、ポート番号を含んだ文字列を指定します。$error_code$error_message引数には、接続時にエラーが発生した場合、そのエラーコードとエラーメッセージが格納されます。$timeout引数には、接続を試みる際のタイムアウト時間を秒単位で指定します。タイムアウト時間を設定することで、接続がいつまでも確立されない状況を回避できます。

stream_socket_client関数は、接続に成功した場合、ストリームリソースを返します。このリソースを使用して、ソケットとのデータの送受信を行うことができます。接続に失敗した場合は、falseを返します。

サンプルコードでは、まずstream_socket_client関数を使用して "tcp://example.com:80" への接続を試みます。接続に成功した場合、HTTP GETリクエストを送信し、レスポンスを読み込んで表示します。最後に、fclose関数を使用してストリームを閉じます。エラーが発生した場合は、エラーメッセージを表示します。この例は、基本的なHTTPクライアントの実装を示しており、ネットワークプログラミングの入門として役立ちます。

stream_socket_clientはソケット接続を確立する関数です。引数$addressには、"tcp://example.com:80" のように、プロトコル、ホスト名、ポート番号を正しく指定する必要があります。$errno$errstrは、接続に失敗した場合にエラーコードとエラーメッセージが格納される変数です。これらは省略可能ですが、エラー処理を行う場合は必ず指定してください。$timeoutは接続試行のタイムアウト時間を秒単位で指定します。タイムアウトを設定することで、応答のないサーバーへの接続を無限に待つことを避けられます。接続後はfwriteでデータを送信し、fgetsfeofで応答を読み込みます。最後にfcloseでストリームを閉じることを忘れないでください。

PHPでWebSocketクライアント接続する

1<?php
2
3/**
4 * WebSocketクライアント接続サンプル
5 *
6 * @param string $address WebSocketサーバーのアドレス (例: tcp://localhost:8000)
7 * @param string $message 送信するメッセージ
8 * @return string|false 受信したメッセージ、または接続失敗時にfalse
9 */
10function websocket_client(string $address, string $message): string|false
11{
12    $context = stream_context_create([
13        'socket' => [
14            'tcp_nodelay' => true, // Nagleアルゴリズムを無効化 (レイテンシ削減)
15        ],
16    ]);
17
18    $error_code = 0;
19    $error_message = '';
20    $timeout = 5; // 接続タイムアウト (秒)
21
22    $socket = stream_socket_client(
23        $address,
24        $error_code,
25        $error_message,
26        $timeout,
27        STREAM_CLIENT_CONNECT,
28        $context
29    );
30
31    if (!$socket) {
32        error_log("Failed to connect: $error_message (code: $error_code)");
33        return false;
34    }
35
36    fwrite($socket, $message); // メッセージを送信
37    $response = fread($socket, 4096); // 応答を受信 (最大4096バイト)
38    fclose($socket); // ソケットを閉じる
39
40    return $response;
41}
42
43// 使用例:
44$address = 'tcp://localhost:8000'; // WebSocketサーバーのアドレス
45$message = "Hello, WebSocket Server!";
46$response = websocket_client($address, $message);
47
48if ($response !== false) {
49    echo "Received: " . $response . PHP_EOL;
50} else {
51    echo "Connection failed." . PHP_EOL;
52}
53
54?>

PHPのstream_socket_client関数は、ソケットを使用してサーバーに接続するための関数です。このサンプルコードでは、stream_socket_client関数を利用してWebSocketクライアントを実装しています。

websocket_client関数は、WebSocketサーバーのアドレス $address と、送信するメッセージ $message を引数に取ります。stream_socket_client関数を使用してサーバーに接続し、メッセージを送信して応答を受信します。

stream_socket_client関数の第一引数 $address は接続先のアドレスを指定します。第二引数 $error_code と第三引数 $error_message は、接続に失敗した場合にエラーコードとエラーメッセージが格納される変数を参照渡しで指定します。第四引数 $timeout は接続のタイムアウト時間を秒単位で指定します。第五引数 $flags は接続オプションを指定します。ここでは STREAM_CLIENT_CONNECT を指定して接続を確立します。第六引数 $context はストリームコンテキストを指定します。サンプルコードでは、Nagleアルゴリズムを無効にするための設定を行っています。

関数は、サーバーからの応答を文字列で返し、接続に失敗した場合は false を返します。

使用例では、ローカルホストの8000番ポートでWebSocketサーバーが動作していることを想定し、"Hello, WebSocket Server!"というメッセージを送信しています。サーバーからの応答があれば、受信したメッセージを表示し、接続に失敗した場合はその旨を表示します。

このサンプルコードは、WebSocketクライアントの基本的な接続とメッセージ送受信の流れを理解するのに役立ちます。stream_socket_client関数は、WebSocketに限らず、様々な種類のソケット通信に使用できます。

stream_socket_client関数は、指定されたアドレスにソケット接続を確立するために使用されます。WebSocketクライアントとして利用する場合、アドレスはtcp://またはssl://で始まる必要があります。

サンプルコードでは、タイムアウト時間を設定し、エラーコードとエラーメッセージを変数で受け取っています。接続に失敗した場合、これらの変数をチェックすることで、原因を特定できます。stream_context_createでソケットオプションを設定し、Nagleアルゴリズムを無効にすることで、レイテンシを削減できます。

fwriteで送信するメッセージは、WebSocketプロトコルに従った形式である必要があります。サンプルコードでは単純な文字列を送信していますが、実際にはハンドシェイクリクエストやデータフレームを適切に構成する必要があります。freadで受信するデータの最大サイズは4096バイトに制限されています。より大きなデータを受信する場合は、ループ処理などを検討してください。最後に、fcloseでソケットを閉じることを忘れないでください。

PHP stream_socket_client でタイムアウト接続する

1<?php
2
3/**
4 * 指定されたホストとポートにタイムアウトを設定して接続を試みます。
5 *
6 * @param string $host 接続先のホスト名またはIPアドレス
7 * @param int $port 接続先のポート番号
8 * @param float $timeout 接続試行の最大時間(秒)。この時間を超えるとタイムアウトと判断されます。
9 * @return void
10 */
11function connectWithTimeout(string $host, int $port, float $timeout = 5.0): void
12{
13    // 接続先のアドレスをTCPプロトコル形式で構築
14    $address = "tcp://{$host}:{$port}";
15    $errorCode = null;    // エラーコードを格納する変数
16    $errorMessage = null; // エラーメッセージを格納する変数
17
18    echo "Attempting to connect to {$address} with a timeout of {$timeout} seconds...\n";
19
20    // stream_socket_client 関数を使用してソケット接続を試みます。
21    // 第4引数に $timeout を指定することで、接続試行の最大時間を設定できます。
22    $socket = stream_socket_client(
23        $address,          // 接続先アドレス
24        $errorCode,        // エラーコードが設定される参照引数
25        $errorMessage,     // エラーメッセージが設定される参照引数
26        $timeout           // 接続試行のタイムアウト時間(秒)
27    );
28
29    if ($socket === false) {
30        // 接続に失敗した場合
31        echo "Failed to connect to {$address}.\n";
32        if ($errorCode !== null) {
33            echo "Error Code: {$errorCode}\n";
34        }
35        if ($errorMessage !== null) {
36            echo "Error Message: {$errorMessage}\n";
37        }
38    } else {
39        // 接続に成功した場合
40        echo "Successfully connected to {$address}!\n";
41        // 接続が確立されたら、ソケットリソースを閉じます
42        fclose($socket);
43        echo "Connection to {$address} closed.\n";
44    }
45}
46
47// --- サンプルコードの実行例 ---
48
49// 例1: GoogleのWebサーバー (TCP/80) への接続を5秒のタイムアウトで試みます。
50// 通常、この接続はすぐに成功します。
51echo "--- Example 1: Successful connection ---\n";
52connectWithTimeout('www.google.com', 80, 5.0);
53echo "\n";
54
55// 例2: 存在しない可能性が高いIPアドレス (予約されたテスト用IP) とポートへの接続を
56// 短いタイムアウト (2秒) で試みます。
57// この場合、タイムアウトまたは接続拒否のエラーが発生する可能性が高いです。
58echo "--- Example 2: Connection likely to fail or timeout ---\n";
59connectWithTimeout('192.0.2.1', 80, 2.0); // 192.0.2.1 はRFC 5737でテスト用に予約されたIPアドレスです。
60echo "\n";

PHPのstream_socket_client関数は、ネットワーク接続、特にTCP/IPソケット接続を確立するために使用されます。この関数は、指定されたホストとポートに対してクライアント側のソケット接続を試みる際に役立ちます。

主な引数として、$addressにはtcp://ホスト名:ポート番号のような形式で接続先のアドレスを指定します。$timeout引数は、接続試行の最大時間を秒単位で設定するもので、この時間を超えても接続が確立されない場合にタイムアウトと判断し、処理を中断します。これにより、応答のないサーバーへの接続試行によってプログラムが長時間停止するのを防ぐことができます。

また、$error_code$error_messageは参照渡しで、接続に失敗した場合に発生したエラーの詳細情報がこれらの変数に格納されます。

関数が成功すると、確立されたソケット接続を表すリソースが返されます。接続に失敗した場合はfalseが返されるため、戻り値を確認して適切なエラー処理を行うことが重要です。

サンプルコードのconnectWithTimeout関数では、このstream_socket_client関数の第4引数として$timeoutを設定し、接続試行時間を制御しています。これにより、接続の成功・失敗に関わらず、指定された時間内に処理が完了するようになっています。失敗時にはエラーコードやメッセージを表示し、接続状況をユーザーに分かりやすく伝えています。

このサンプルコードでは、stream_socket_client関数の第4引数で接続試行の最大時間、すなわちタイムアウトを設定しています。これはデータ送受信ではなく、接続確立そのものの時間制限である点にご注意ください。接続に失敗した際は戻り値がfalseとなるため、厳密な比較(=== false)で確認することが重要です。また、第2・3引数にはエラーコードとエラーメッセージが参照渡しで格納されるため、接続失敗時にはこれらを参照し、原因を特定する手助けとしてください。接続が成功し、ソケットリソースを取得した場合は、処理終了後に必ずfclose()関数でソケットを閉じるようにしてください。これを怠ると、リソースが解放されずにシステムに負荷がかかり続ける可能性があります。

PHP: stream_socket_clientでプロキシ接続する

1<?php
2
3/**
4 * HTTPプロキシサーバー経由で目的のホストにソケット接続を確立します。
5 * この関数は、プロキシサーバーへの接続に stream_socket_client を使用し、
6 * その後、HTTP CONNECTメソッドを介して目的のホストへのトンネルを確立します。
7 *
8 * @param string $targetHost 接続したい目的のホスト名またはIPアドレス (例: 'example.com')
9 * @param int $targetPort 接続したい目的のポート番号 (例: 80, 443)
10 * @param string $proxyHost HTTPプロキシサーバーのホスト名またはIPアドレス (例: '127.0.0.1')
11 * @param int $proxyPort HTTPプロキシサーバーのポート番号 (例: 8080)
12 * @param int|null $errorCode エラーが発生した場合、エラーコードが格納されます (参照渡し)
13 * @param string|null $errorMessage エラーが発生した場合、エラーメッセージが格納されます (参照渡し)
14 * @param float|null $timeout 接続および応答のタイムアウト時間(秒)。nullの場合はPHPのデフォルト設定を使用します。
15 * @return resource|false 接続が成功した場合、確立されたソケットリソースを返します。失敗した場合は false を返します。
16 */
17function connectThroughProxy(
18    string $targetHost,
19    int $targetPort,
20    string $proxyHost,
21    int $proxyPort,
22    ?int &$errorCode = null,
23    ?string &$errorMessage = null,
24    ?float $timeout = null
25): resource|false {
26    // プロキシサーバーへの接続アドレスを構築
27    $proxyAddress = "tcp://{$proxyHost}:{$proxyPort}";
28
29    // stream_socket_client を使用してプロキシサーバーに直接接続します。
30    // この段階では、まだ目的のホストではなく、プロキシサーバーへの接続です。
31    $proxySocket = stream_socket_client(
32        $proxyAddress,
33        $errorCode,
34        $errorMessage,
35        $timeout ?? (float)ini_get("default_socket_timeout") // タイムアウト設定
36    );
37
38    if (!$proxySocket) {
39        // プロキシサーバーへの接続自体が失敗した場合
40        $errorMessage = $errorMessage ?? "Failed to connect to proxy server at {$proxyAddress}";
41        return false;
42    }
43
44    // プロキシサーバーに対して、目的のホストへのトンネルを要求するCONNECTリクエストを送信します。
45    $connectRequest = "CONNECT {$targetHost}:{$targetPort} HTTP/1.1\r\n";
46    $connectRequest .= "Host: {$targetHost}:{$targetPort}\r\n";
47    // プロキシ認証が必要な場合は、Authorizationヘッダーを追加します。
48    // 例: $connectRequest .= "Proxy-Authorization: Basic " . base64_encode("username:password") . "\r\n";
49    $connectRequest .= "\r\n"; // HTTPリクエストヘッダーの終わりを示す空行
50
51    fwrite($proxySocket, $connectRequest);
52
53    // プロキシサーバーからの応答を読み込みます。
54    // 最初の行はHTTPステータスライン (例: HTTP/1.1 200 Connection established) です。
55    $responseLine = fgets($proxySocket, 4096);
56    if ($responseLine === false) {
57        $errorCode = E_USER_WARNING; // 一般的なエラーコード
58        $errorMessage = "Failed to read response from proxy server after CONNECT request.";
59        fclose($proxySocket);
60        return false;
61    }
62
63    // HTTPステータスコードを解析し、接続が確立されたか確認します。
64    if (preg_match('/^HTTP\/1\.\d\s+(\d+)/', $responseLine, $matches)) {
65        $statusCode = (int)$matches[1];
66        if ($statusCode === 200) {
67            // 200 OK (Connection established) の場合、残りのヘッダーを読み飛ばします。
68            // これ以降、このソケットは目的のホストへの透過的なトンネルとして機能します。
69            while (($headerLine = fgets($proxySocket, 4096)) !== false && trim($headerLine) !== '') {
70                // ヘッダーを読み捨てる
71            }
72            return $proxySocket; // 接続成功
73        } else {
74            // 200 OK 以外のステータスコードはエラーと判断します。
75            $errorCode = $statusCode;
76            $errorMessage = "Proxy server returned error: {$statusCode} {$responseLine}";
77            fclose($proxySocket);
78            return false;
79        }
80    } else {
81        // プロキシサーバーからの応答が期待されるHTTP形式でない場合
82        $errorCode = E_USER_WARNING;
83        $errorMessage = "Unexpected response format from proxy server: {$responseLine}";
84        fclose($proxySocket);
85        return false;
86    }
87}
88
89// --- 使用例 ---
90// 接続したい実際のターゲットホストとポート
91$targetHost = 'example.com';
92$targetPort = 80; // HTTP接続の場合
93// $targetPort = 443; // HTTPS接続の場合
94
95// 使用するHTTPプロキシサーバーの情報
96// !! 注意: ここを実際のプロキシサーバーのアドレスとポートに置き換えてください !!
97// (例: ローカルでSquidを動かしている場合 '127.0.0.1:3128' など)
98$proxyHost = 'your_proxy_host';
99$proxyPort = 8080;
100
101$errorCode = null;
102$errorMessage = null;
103$timeout = 10.0; // 接続と応答のタイムアウトを10秒に設定
104
105echo "Attempting to connect to {$targetHost}:{$targetPort} via proxy {$proxyHost}:{$proxyPort}...\n";
106
107$socket = connectThroughProxy(
108    $targetHost,
109    $targetPort,
110    $proxyHost,
111    $proxyPort,
112    $errorCode,
113    $errorMessage,
114    $timeout
115);
116
117if ($socket) {
118    echo "Successfully connected to {$targetHost}:{$targetPort} via proxy!\n";
119    echo "Socket resource type: " . get_resource_type($socket) . "\n\n";
120
121    // プロキシ経由で目的のホストに接続されたソケットを使用して、HTTPリクエストを送信します。
122    // ここからの通信は、直接目的のホストと行われるのと同様です。
123    $request = "GET / HTTP/1.1\r\n";
124    $request .= "Host: {$targetHost}\r\n";
125    $request .= "Connection: Close\r\n\r\n"; // リクエストの終わり
126
127    fwrite($socket, $request);
128    echo "Sent HTTP GET request to {$targetHost}.\n\n";
129
130    // 目的のホストからの応答を読み込み、出力します。
131    echo "Received response:\n";
132    while (!feof($socket)) {
133        echo fgets($socket, 4096);
134    }
135
136    // 接続を閉じます。
137    fclose($socket);
138    echo "\nConnection closed.\n";
139} else {
140    echo "Failed to connect via proxy.\n";
141    echo "Error [{$errorCode}]: {$errorMessage}\n";
142    if ($errorCode && $errorCode !== 200) {
143        echo "Please check if the proxy server is running and accessible at {$proxyHost}:{$proxyPort}.\n";
144        echo "Also, ensure the proxy configuration allows CONNECT requests to {$targetHost}:{$targetPort}.\n";
145    }
146}

PHP 8のstream_socket_client関数は、TCP/UDPなどのネットワークソケット接続を確立するために使用されます。このサンプルコードは、stream_socket_clientを応用し、HTTPプロキシサーバー経由で目的のホストに接続する方法を具体的に示しています。

stream_socket_client関数は、第一引数$addressで指定されたサーバーに接続を試み、成功するとネットワーク通信に利用できるソケットリソースを返します。接続に失敗した場合はfalseを返し、その際、引数$error_code$error_messageに詳細なエラー情報が参照渡しで格納されます。$timeout引数で接続試行のタイムアウト時間を設定することも可能です。

サンプルコード内のconnectThroughProxy関数は、まずstream_socket_clientを使ってプロキシサーバー自体に接続します。次に、プロキシサーバーに対してHTTP CONNECTメソッドを用いたリクエストを送信し、目的のホストへの「トンネル」の確立を要求します。プロキシサーバーがHTTP 200 OKで応答すれば、stream_socket_clientが返したソケットリソースは、以降、プロキシを介して目的のホストと直接データ送受信を行うための透過的な通路として機能します。これにより、クライアントはプロキシの裏側にあるホストと通信できるようになります。エラー発生時には、関数はfalseを返し、参照渡しで渡された引数にエラーコードとメッセージが設定されますので、適切なエラー処理を行うことが重要です。

このサンプルコードは、HTTPプロキシ経由でソケット接続を行う際の注意点を示しています。まず、$proxyHost$proxyPortには、ご自身の環境で利用可能なプロキシサーバーの情報を正確に設定する必要があります。stream_socket_clientは最初にプロキシサーバーとの接続を確立し、その後にHTTP CONNECTメソッドで目的ホストへのトンネルを要求する二段階の動作をします。接続や通信が失敗した場合は、参照渡しの$errorCode$errorMessageで具体的なエラー情報を確認し、原因を特定してください。プロキシサーバーが認証を要求する場合、Proxy-Authorizationヘッダーの追加が必要です。また、$timeoutパラメータで接続タイムアウトを設定し、リソース使用後は必ずfcloseでソケットを閉じるようにしてください。

関連コンテンツ

関連IT用語

関連プログラミング言語