I'm confused about the rerturn value of socket_recvfrom(), it said -1 when failed, but when I call like this:
if (($len = @socket_recvfrom($sock, $result, 32, 0, $ip, $port)) == -1) {
if ($this->_debug) {
echo "socket_read() failed: " . socket_strerror(socket_last_error()) . "\n";
}
return false;
}
variable $len = false, when I change the buffer length from 32 to 4096, it becomes right.
socket_recvfrom
(PHP 4 >= 4.1.0, PHP 5)
socket_recvfrom — 接続しているかどうかによらず、ソケットからデータを受信する
説明
socket_recvfrom() 関数は、 ポート port (AF_UNIX 型のソケットである場合を除く) 上の name から受信した len バイトのデータを buf に格納します。 socket_recvfrom() は、 接続済みのソケットだけでなく接続していないソケットに対しても使用可能です。 さらに、フラグを指定することでこの関数の挙動を設定できます。
name と port は参照渡しとしなければなりません。接続していないソケットの場合は、 name はリモートホストの IP アドレスか UNIX ソケットへのパスとなります。接続済みのソケットの場合は、 name は NULL とします。 また、AF_INET あるいは AF_INET6 形式のまだ接続していないソケットの場合、 port にはリモートホストのポート番号を指定します。
パラメータ
- socket
-
socket には、 socket_create() で作成したソケットリソースを指定します。
- buf
-
受信したデータが buf に格納されます。
- len
-
最大 len バイトまでのデータをリモートホストから取得します。
- flags
-
flags の値は、以下のフラグの任意の組み合わせを 論理 OR 演算子 (|) で連結したものとなります。
flags に使用できる値 フラグ 説明 MSG_OOB 帯域外 (out-of-band) のデータを処理する。 MSG_PEEK 受信キューの先頭にあるデータを受信し、 そのデータをそのままキューに残しておく。 MSG_WAITALL 少なくとも len バイト受信するまではブロックする。 しかし、もし何らかのシグナルを受信したりリモートホストとの接続が切断された場合は これより少ないバイト数を返す可能性がある。 MSG_DONTWAIT 通常はブロックする場面であってもそのまま return する。 - name
-
AF_UNIX 型のソケットの場合は、 name はファイルへのパスとなります。 それ以外の場合は、未接続のソケットの場合には name はリモートホストの IP アドレスとなります。 接続済みソケットの場合は NULL となります。
- port
-
この引数は AF_INET 型あるいは AF_INET6 型のソケットに対してのみ適用され、 データを受信するリモートホストのポートを指定します。 接続済みソケットの場合は port は NULL となります。
返り値
socket_recvfrom() は、受信したバイト数を返します。 あるいはエラー時には -1 を返します。 エラーコードを取得するには socket_last_error() をコールします。取得したエラーコードを socket_strerror() に渡すと、 そのエラーについての説明を得ることができます。
例
例1 socket_recvfrom() の例
<?php
error_reporting(E_ALL | E_STRICT);
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($socket, '127.0.0.1', 1223);
$from = "";
$port = 0;
socket_recvfrom($socket, $buf, 12, 0, $from, $port);
echo "リモートアドレス $from のポート $port から $buf を受信しました" . PHP_EOL;
?>
この例は、127.0.0.1 のポート 1223 との UDP ソケットを確立し、受信したデータを最大 12 バイトまで表示します。
変更履歴
| バージョン | 説明 |
|---|---|
| 4.3.0 | socket_recvfrom() はバイナリセーフとなりました。 |
参考
- socket_recv() - 接続したソケットからデータを受信する
- socket_send() - 接続したソケットにデータを送信する
- socket_sendto() - 接続しているかどうかによらずソケットにメッセージを送信する
- socket_create() - ソケット(通信時の終端)を作成する
socket_recvfrom
08-Nov-2007 02:56
02-Oct-2006 02:27
DNS RELAY USING UDP SOCKETS
<?php
while(TRUE) {
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
if($socket === FALSE)
{
echo 'Socket_create failed: '.socket_strerror(socket_last_error())."\n";
}
if(!socket_bind($socketD, "0.0.0.0", 53)) {
socket_close($socketD);
echo 'socket_bind failed: '.socket_strerror(socket_last_error())."\n";
}
socket_recvfrom($socket,$buf,65535,0,$clientIP,$clientPort);
$stz = bin2hex($buf);
$tx = "";
for($i=0;$i<(strlen($stz)-26-10)/2;$i++)
{
$e = "00";
$e[0] = $stz[$i*2+26];
$e[1] = $stz[$i*2+27];
$f = hexdec($e);
if($f > 0 && $f < 32) $tx .= "."; else
$tx .= sprintf("%c",$f);
}
echo "$clientIP <".$tx.">\n";
$fp = fsockopen("udp://72.174.110.4",53,$errno,$errstr);
if (!$fp)
{
echo "ERROR: $errno - $errstr<br />\n";
}
else
{
fwrite($fp,$buf);
$ret = $buf;
$ret = fread($fp,667);
fclose($fp);
}
}
socket_send($socket,$ret,667,0);
}
?>
22-Feb-2005 08:17
This function is very handy when dealing with UDP connections, because it enables you to know who's the client who connected to your socket. Bear in mind that UDP doesn't care about the source of the connection, the packets may be annonymous or even faked. No check is required.
If you want to listen on an UDP socket and answer to the client, read my comment on socket_listen() -> http://www.php.net/manual/en/function.socket-listen.php