サーチ…


TCPクライアントソケット

TCP(伝送制御プロトコル)を使用するソケットを作成すると、

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

ソケットが正常に作成されていることを確認します。 onSocketFailure関数は、このトピックの「 ソケットエラーの処理」の例にあります。

if(!is_resource($socket)) onSocketFailure("Failed to create socket");

ソケットを指定されたアドレスに接続する

接続が失敗した場合、2行目は正常に失敗します。

socket_connect($socket, "chat.stackoverflow.com", 6667)
        or onSocketFailure("Failed to connect to chat.stackoverflow.com:6667", $socket);

サーバーへのデータの送信

socket_write関数はソケットを通してバイトを送信します。 PHPでは、バイト配列は文字列で表され、通常はエンコーディングを区別しません。

socket_write($socket, "NICK Alice\r\nUSER alice 0 * :Alice\r\n");

サーバーからのデータ受信

次のスニペットは、 socket_read関数を使用してサーバーからデータを受信します。

PHP_NORMAL_READを3番目のパラメータとして渡すと\r / \nバイトまで読み込まれ、このバイトが戻り値に含まれます。

反対に、 PHP_BINARY_READ渡すと、必要な量のデータがストリームから読み込まれます。

先にsocket_set_nonblockが呼び出され、 PHP_BINARY_READが使用された場合、 socket_readは直ちにfalseを返しfalse 。それ以外の場合、メソッドは、(2番目のパラメータの長さに達するか、または行末に到達する)十分なデータが受信されるか、ソケットが閉じられるまでブロックします。

この例では、IRCサーバーと推定されるデータを読み取ります。

while(true) {
    // read a line from the socket
    $line = socket_read($socket, 1024, PHP_NORMAL_READ);
    if(substr($line, -1) === "\r") {
        // read/skip one byte from the socket
        // we assume that the next byte in the stream must be a \n.
        // this is actually bad in practice; the script is vulnerable to unexpected values
        socket_read($socket, 1, PHP_BINARY_READ);
    }

    $message = parseLine($line);
    if($message->type === "QUIT") break;
}

ソケットを閉じる

ソケットを閉じると、ソケットとそれに関連するリソースが解放されます。

socket_close($socket);

TCPサーバーソケット

ソケットの作成

TCPを使用するソケットを作成します。これは、クライアントソケットの作成と同じです。

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

ソケットバインディング

指定されたネットワーク(パラメータ2)から特定のポート(パラメータ3)への接続をソケットにバインドします。

2番目のパラメータは通常"0.0.0.0" 、すべてのネットワークからの接続を受け付けます。それはまた、

socket_bindのエラーの一般的な原因の1つは、指定されたアドレスがすでに別のプロセスにバインドされていることです。ソケットが解放されるように、通常は他のプロセスが強制終了され(通常、誤って重大なプロセスを停止するのを防ぐために手動で)

socket_bind($socket, "0.0.0.0", 6667) or onSocketFailure("Failed to bind to 0.0.0.0:6667");

リスニングするソケットを設定する

ソケットがsocket_listenを使用して着信接続をsocket_listenます。 2番目のパラメータは、それらが受け入れられる前にキューイングを可能にする接続の最大数です。

socket_listen($socket, 5);

接続の処理

TCPサーバーは、実際には子接続を処理するサーバーです。 socket_acceptは新しい子接続を作成します。

$conn = socket_accept($socket);

socket_acceptからの接続のためのデータ転送は、 TCPクライアントソケットのものと同じです。

この接続を閉じるときは、 socket_close($conn);呼び出しsocket_close($conn);直接。これは元のTCPサーバーソケットには影響しません。

サーバーを閉じる

一方、 socket_close($socket);サーバーが使用されなくなったときに呼び出される必要があります。これによりTCPアドレスも解放され、他のプロセスがアドレスにバインドできるようになります。

ソケットエラーの処理

socket_last_errorは、ソケット拡張から最後のエラーのエラーIDを取得するために使用できます。

socket_strerrorは、IDを人間が読める文字列に変換するために使用できます。

function onSocketFailure(string $message, $socket = null) {
    if(is_resource($socket)) {
        $message .= ": " . socket_strerror(socket_last_error($socket));
    }
    die($message);
}

UDPサーバーソケット

UDP(ユーザデータグラムプロトコル)サーバは、TCPと異なり、ストリームベースではありません。これはパケットベースです。つまり、クライアントはサーバーに「パケット」と呼ばれる単位でデータを送信し、クライアントはそのアドレスでクライアントを識別します。 (同じクライアントからのデータがsocket_acceptによって作成された特定のリソースによって処理されるTCPとは異なり、)同じクライアントから送られた異なるパケットを関連付ける組み込み関数はありません。 UDPパケットが到着するたびに、新しいTCP接続が受け入れられて閉じられると考えられます。

UDPサーバーソケットの作成

$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);

ソケットにアドレスをバインドする

パラメータはTCPサーバと同じです。

socket_bind($socket, "0.0.0.0", 9000) or onSocketFailure("Failed to bind to 0.0.0.0:9000", $socket);

パケットを送信する

この行は、UDPパケットの$data$address$port送り$port

socket_sendto($socket, $data, strlen($data), 0, $address, $port);

パケットを受信する

次のスニペットは、クライアントインデックス方式でUDPパケットを管理しようとします。

$clients = [];
while (true){
    socket_recvfrom($socket, $buffer, 32768, 0, $ip, $port) === true
            or onSocketFailure("Failed to receive packet", $socket);
    $address = "$ip:$port";
    if (!isset($clients[$address])) $clients[$address] = new Client();
    $clients[$address]->handlePacket($buffer);
}

サーバーを閉じる

socket_closeは、UDPサーバーソケットリソースで使用できます。これによりUDPアドレスが解放され、他のプロセスがこのアドレスにバインドできるようになります。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow