socket_create_pair

(PHP 4 >= 4.1.0, PHP 5)

socket_create_pair -- 区別できないソケットの組を作成し、配列に保存する

説明

bool socket_create_pair ( int domain, int type, int protocol, array &fd )

socket_create_pair() は、接続されており区別できない 2 つのソケットを作成し、それを fd に保存します。 この関数は、一般に IPC(InterProcess Communication: プロセス間通信) で使用します。

domain は、ソケットで使用するプロトコルの 種類を指定します。

表 1. 使用可能な アドレス/プロトコル の種類

ドメイン説明
AF_INET IPv4 Internet に基づいたプロトコルです。TCP および UDP が一般的に 使用されます。Windows でのみサポートされます。
AF_INET6 IPv6 Internet に基づいたプロトコルです。TCP および UDP が一般的に 使用されます。PHP 5.0.0 以降でサポートされるようになりました。 Windows でのみサポートされます。
AF_UNIX ローカル通信プロトコルです。効率的でオーバーヘッドが少なく、 IPC(プロセス間通信)に適した形式です。

type では、ソケットが使用する通信の形式を 選択します。

表 2. 使用可能なソケットの型

説明
SOCK_STREAM シーケンシャルで信頼性が高く、完全双方向であるコネクションベースの バイトストリームです。帯域外のデータ転送機能がサポートされて いるかもしれません。TCP プロトコルは、このソケット型に基づいています。
SOCK_DGRAM データグラム(コネクションレスで信頼性の低い、固定長メッセージ) をサポートします。UDP プロトコルは、このソケット型に基づいています。
SOCK_SEQPACKET シーケンシャルで信頼性の高い、双方向のコネクションベースの データ転送で、固定長のデータグラムを取り扱います。 利用する側は、1 度の読み込みコールでパケット全体を読み込む必要が あります。
SOCK_RAW ネットワーク上のデータを直接扱います。独自のプロトコルを実装する 際などに、この特殊な型が使用可能です。このソケット型の一般的な 使用法は、ICMP リクエスト(ping や traceroute など)を扱うことです。
SOCK_RDM 信頼性の高いデータグラム層で、データの到着順を保証しません。 ほとんどの OS 上では、これは実装されていません。

protocol は、指定した domain の中の特定のプロトコルを指定します。これは、返されるソケットとの通信に 使用されます。使用可能な値の名前は getprotobyname() で取得可能です。もし要求されるプロトコルが TCP あるいは UDP の場合、 対応する定数 SOL_TCP および SOL_UDP も使用可能です。

表 3. 通信プロトコル

名前説明
icmp Internet Control Message Protocol は、データグラム通信において ゲートウェイとホストの間でエラーの報告をする際に使用されます。 ICMP を使用するアプリケーションの例は "ping" コマンドです(最近のほとんどの OS に搭載されています)。
udp User Datagram Protocol はコネクションレスの信頼できないプロトコルで、 固定長のレコードを扱います。この特徴のおかげで、UDP プロトコルの オーバーヘッドは最小限ですみます。
tcp Transmission Control Protocol は信頼性の高い、コネクションに基づいた、 ストリーム試行の完全双方向プロトコルです。TCP は、すべての データパケットが送信した順にきちんと受け取られることを保証します。 通信の途中でパケットが失われた場合は、受け取り先ホストがパケットを 認識できるまで TCP は自動的にそのパケットを再送信します。 信頼性とパフォーマンスのため、TCP 実装はその下層のデータグラム通信 レイヤにおいて適当なバイト数でデータを区切っています。そのため、 TCP アプリケーションはレコードの一部のみが送られてくる場合が ありうることを想定しておかねばなりません。

例 1. socket_create_pair() の例

<?php
$sockets
= array();
/* ソケットの組の設定 */
if (socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets) === false) {
    echo
"socket_create_pair failed. Reason: ".socket_strerror(socket_last_error());
}
/* データの送受信 */
if (socket_write($sockets[0], "ABCdef123\n", strlen("ABCdef123\n")) === false) {
    echo
"socket_write() failed. Reason: ".socket_strerror(socket_last_error($sockets[0]));
}
if ((
$data = socket_read($sockets[1], strlen("ABCdef123\n"), PHP_BINARY_READ) === false) {
    echo
"socket_read() failed. Reason: ".socket_strerror(socket_last_error($sockets[1]));
}
var_dump($data);

/* ソケットのクローズ */
socket_close($sockets[0]);
socket_close($sockets[1]);
?>

例 2. socket_create_pair() での IPC の例

<?php
$ary
= array();
$strone = 'Message From Parent.';
$strtwo = 'Message From Child.';
if (
socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $ary) === false) {
    echo
"socket_create_pair() failed. Reason: ".socket_strerror(socket_last_error());
}
$pid = pcntl_fork();
if (
$pid == -1) {
    echo
'プロセスを fork できません。';
} elseif (
$pid) {
    
/* 親プロセス */
    
socket_close($ary[0]);
    if (
socket_write($ary[1], $strone, strlen($strone)) === false) {
        echo
"socket_write() failed. Reason: ".socket_strerror(socket_last_error($ary[1]));
    }
    if (
socket_read($ary[1], strlen($strtwo), PHP_BINARY_READ) == $strtwo) {
        echo
"Recieved $strtwo\n";
    }
    
socket_close($ary[1]);
} else {
    
/* 子プロセス */
    
socket_close($ary[1]);
    if (
socket_write($ary[0], $strtwo, strlen($strtwo)) === false) {
        echo
"socket_write() failed. Reason: ".socket_strerror(socket_last_error($ary[0]));
    }
    if (
socket_read($ary[0], strlen($strone), PHP_BINARY_READ) == $strone) {
        echo
"Recieved $strone\n";
    }
    
socket_close($ary[0]);
}
?>