问题
次の段代を参照
$word = 'HELLO';
$conf = array(
array('ip'=>'10.1.146.133', 'port'=>2001),
array('ip'=>'10.1.146.133', 'port'=>2002)
);
関数 udpGet($word, $ip, $port)
{
$sock =ソケット_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_set_option($sock, SOL_SOCKET, SO_SNDTIMEO, array('sec'=>2, 'usec'=>0));
socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, array('sec'=>2, 'usec'=>0));
socket_sendto($sock, $word, strlen($word), 0x100, $ip, $port);
socket_recvfrom($sock, $result, 8192, 0, $host, $port);
socket_close($sock);
return $result;
}
for ($i=0; $i
{
$res = udpGet($word, $conf[$i]['ip'], $conf[$i]['port']);
var_dump($res);
}
は、継続的に UPD を使用して 2 つのサーバーにデータを送信します (説明のため、この場所のサーバーは最简単一の回射逻辑を使用します)、結果一切の流れが正常であれば、クライアント端末しかし、サービスが終了したため問題がありますか?現在、クライアントの経過時間は 2 秒で、2001 ポートは 3 秒のデータ送信を実行しますが、2002 ポートはサービスが提供されません。 、 下の結果は何ですか?「2 つの NULL!」、直接的にはこれがこの応答です。これも認められる場合、 なら恭喜さん、応答します。
实际の応答案:
NULL
string(5) "HELLO"
分析
tcpdump パケットを使用すると、次のような結果が得られます
(133 はサーバー、163 はクライアント、クライアント PHP バージョン 5.3.1、Linux カーネル 2.6.16)
12:01:39.014658 IP 10.1.146.163.40678 > 10.1.146.133.2001: UDP、長さ 5
12:01:41.015121 IP 10.1.146.163.40678 > 10.1.146.133.2002: UDP、長さ 5
12:01:42.016103 IP 10.1.146.133.2001 > 10.1.146.163.40678: UDP、長さ 5
2 つのリクエストは送信と受信に異なる一時ポートを使用するはずですが、パケット キャプチャの結果から、クライアントはソケット作成を 2 回実行しましたが、実際には同じ一時ポートが使用されていました。データを送受信するためのポート (40678) !これにより、2 番目のリクエストが最初のリクエストからの応答パケットを受信します。
これはシステムのバグとみなすべきだと思われます。実験の結果、この問題は一部のシステム (例えば、Linux カーネル 2.6) にのみ存在することが判明しました。 32+php5.2.3 ではこの問題は発生しません。
解決策
送受信の都度ソケットポートを指定します。以下の赤いコードに示されているように。$sock =ソケット_create(AF_INET, SOCK_DGRAM, SOL_UDP);
$sendPort = rand(10240, 60000);
socket_bind($sock, ’10.1.146.163′, $sendPort);
socket_set_option($sock, SOL_SOCKET, SO_SNDTIMEO, array(‘sec’=>2, ‘usec’=>0));
socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, array(‘sec’=>2, ‘usec’=>0));
もちろん、rand ポートが衝突する可能性もありますが、結局のところ、その確率は小さく、問題はかなりの程度解決できます。