如果您在 UDP 通訊端上使用 socket_recvfrom 並將其與 MSG_DONTWAIT 旗標組合使用,如果沒有任何內容可供讀取,它將會引發 PHP 警告。據我所知,除了使用 @ 抑制它之外,沒有辦法解決該警告(也就是說,您無法在呼叫 socket_recvfrom 之前檢查是否有資料)。
(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)
socket_recvfrom — 從通訊端接收數據,無論其是否為面向連線的
$socket
,&$data
,$length
,$flags
,&$address
,&$port
= null
socket_recvfrom() 函式會使用 socket
從 address
位址的 port
埠 (如果 socket 類型不是 AF_UNIX
) 接收 length
位元組的資料到 data
中。 socket_recvfrom() 可用於從已連線和未連線的 socket 收集資料。此外,可以指定一個或多個旗標來修改函式的行為。
address
和 port
必須以傳址方式傳遞。如果 socket 不是面向連線的,address
將被設定為遠端主機的網路協定位址或 UNIX socket 的路徑。如果 socket 是面向連線的,address
將會是 null
。此外,如果是未連線的 AF_INET
或 AF_INET6
socket,port
將包含遠端主機的埠號。
注意:此函式是二進位安全的。
socket
socket
必須是由 socket_create() 先前建立的 Socket 實例。
data
接收到的資料將會被擷取到以 data
指定的變數中。
length
最多會從遠端主機擷取 length
位元組的資料。
flags
flags
的值可以是以下旗標的任意組合,並以二進位 OR (|
) 運算子連接。
旗標 | 說明 |
---|---|
MSG_OOB |
處理頻外資料。 |
MSG_PEEK |
從接收佇列的開頭接收資料,但不將其從佇列中移除。 |
MSG_WAITALL |
阻斷直到至少接收到 length 位元組的資料。但是,如果收到訊號或遠端主機關閉連線,函式可能會返回較少的資料。 |
MSG_DONTWAIT |
設定此旗標後,即使函式通常會被阻斷,它也會立即返回。 |
address
如果 socket 類型是 AF_UNIX
,address
是檔案的路徑。否則,對於未連線的 socket,address
是遠端主機的 IP 位址;如果 socket 是面向連線的,則為 null
。
port
此參數僅適用於 AF_INET
和 AF_INET6
socket,並指定接收資料的遠端埠。如果 socket 是面向連線的,port
將會是 null
。
socket_recvfrom() 會回傳接收到的位元組數,如果發生錯誤則回傳 false
。實際的錯誤碼可以透過呼叫 socket_last_error() 來取得。這個錯誤碼可以傳遞給 socket_strerror() 以取得錯誤的文字說明。
範例 #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 "Received $buf from remote address $from and remote port $port" . PHP_EOL;
?>
此範例將在 127.0.0.1 的連接埠 1223 上啟動一個 UDP 通訊端,並最多印出從遠端主機接收到的 12 個字元。
如果您在 UDP 通訊端上使用 socket_recvfrom 並將其與 MSG_DONTWAIT 旗標組合使用,如果沒有任何內容可供讀取,它將會引發 PHP 警告。據我所知,除了使用 @ 抑制它之外,沒有辦法解決該警告(也就是說,您無法在呼叫 socket_recvfrom 之前檢查是否有資料)。
Windows Sockets 似乎不存在 MSG_DONTWAIT。 但是,socket_set_nonblock() 似乎可以達到同樣的效果。
注意!某些 PHP 版本未定義 MSG_DONTWAIT 旗標(參見 https://bugs.php.net/bug.php?id=48326)
我對 socket_recvfrom() 的回傳值感到困惑,文件說失敗時回傳 -1,但是當我這樣呼叫時:
if (($len = @socket_recvfrom($sock, $result, 32, 0, $ip, $port)) == -1) {
if ($this->_debug) {
echo "socket_read() 失敗:" . socket_strerror(socket_last_error()) . "\n";
}
return false;
}
變數 $len 為 false,當我將緩衝區長度從 32 改為 4096 時,它就正常了。