如果您在 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 = nullsocket_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 將包含遠端主機的埠號。
注意:此函式是二進位安全的。
socketsocket 必須是由 socket_create() 先前建立的 Socket 實例。
data接收到的資料將會被擷取到以 data 指定的變數中。
length最多會從遠端主機擷取 length 位元組的資料。
flagsflags 的值可以是以下旗標的任意組合,並以二進位 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 時,它就正常了。