CakeFest 2024: The Official CakePHP Conference

socket_recvfrom

(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)

socket_recvfrom接続しているかどうかによらず、ソケットからデータを受信する

説明

socket_recvfrom(
    Socket $socket,
    string &$data,
    int $length,
    int $flags,
    string &$address,
    int &$port = null
): int|false

socket_recvfrom() 関数は、 ポート port (AF_UNIX 型のソケットである場合を除く) 上の address から受信した length バイトのデータを data に格納します。 socket_recvfrom() は、 接続済みのソケットだけでなく接続していないソケットに対しても使用可能です。 さらに、フラグを指定することでこの関数の挙動を設定できます。

addressport は参照渡しとしなければなりません。接続していないソケットの場合は、 address はリモートホストの IP アドレスか UNIX ソケットへのパスとなります。接続済みのソケットの場合は、 addressnull とします。 また、AF_INET あるいは AF_INET6 形式のまだ接続していないソケットの場合、 port にはリモートホストのポート番号を指定します。

注意: この関数はバイナリデータに対応しています。

パラメータ

socket

socket には、 socket_create() で作成した Socket クラスのインスタンスを指定します。

data

受信したデータが data に格納されます。

length

最大 length バイトまでのデータをリモートホストから取得します。

flags

flags の値は、以下のフラグの任意の組み合わせを 論理 OR 演算子 (|) で連結したものとなります。

flags に使用できる値
フラグ 説明
MSG_OOB 帯域外 (out-of-band) のデータを処理する。
MSG_PEEK 受信キューの先頭にあるデータを受信し、 そのデータをそのままキューに残しておく。
MSG_WAITALL 少なくとも length バイト受信するまではブロックする。 しかし、もし何らかのシグナルを受信したりリモートホストとの接続が切断された場合は これより少ないバイト数を返す可能性がある。
MSG_DONTWAIT 通常はブロックする場面であってもそのまま return する。
address

AF_UNIX 型のソケットの場合は、 address はファイルへのパスとなります。 それ以外の場合は、未接続のソケットの場合には address はリモートホストの IP アドレスとなります。 接続済みソケットの場合は null となります。

port

この引数は AF_INET 型あるいは AF_INET6 型のソケットに対してのみ適用され、 データを受信するリモートホストのポートを指定します。 接続済みソケットの場合は portnull となります。

戻り値

socket_recvfrom() は、受信したバイト数を返します。 あるいはエラー時には false を返します。 エラーコードを取得するには socket_last_error() をコールします。取得したエラーコードを socket_strerror() に渡すと、 そのエラーについての説明を得ることができます。

変更履歴

バージョン 説明
8.0.0 socket は、Socket クラスのインスタンスになりました。 これより前のバージョンでは、リソース型でした。

例1 socket_recvfrom() の例

<?php

$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 バイトまで表示します。

参考

  • socket_recv() - 接続したソケットからデータを受信する
  • socket_send() - 接続したソケットにデータを送信する
  • socket_sendto() - 接続しているかどうかによらずソケットにメッセージを送信する
  • socket_create() - ソケット(通信時の終端)を作成する

add a note

User Contributed Notes 5 notes

up
3
lorin dot weilenmann at gmail dot com
8 years ago
If you use socket_recvfrom on a UDP socket and combine it with the MSG_DONTWAIT flag, it will raise a PHP Warning if there is nothing to read. AFAIK, there is no way around that warning except suppressing it with @ (i.e. you cannot check if there is data before calling socket_recvfrom).
up
1
ply2attoetensen-project.com
7 years ago
MSG_DONTWAIT doesn't seem to exist in windows sockets. However socket_set_nonblock() seems to do the trick.
up
1
davide dot renzi at gmail dot com
12 years ago
Pay attention! On some PHP version the MSG_DONTWAIT flag is not defined (see https://bugs.php.net/bug.php?id=48326)
up
-3
jaggerwang at gmail dot com
16 years ago
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.
up
-13
ryan_at_ryanfisher_dot_com
17 years ago
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);
}
?>
To Top