


PHP udp的錯包問題
添加時間:2014-12-30 19:36:41
添加:
思海網絡
問題
看下面一段代碼
$word = 'HELLO';
$conf = array(
array('ip'=>'10.1.146.133', 'port'=>2001),
array('ip'=>'10.1.146.133', 'port'=>2002)
);
function udpGet($word, $ip, $port)
{
$sock = socket_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<2; $i++)
{
$res = udpGet($word, $conf[$i]['ip'], $conf[$i]['port']);
var_dump($res);
}
就是連續用UPD向兩個server收發數據(為說明問題,這里的server使用了最簡單的回射邏輯),如果一切流程正常,客戶端會收到兩次‘HELLO’。但是,如果服務端出了問題呢?目前,客戶端的超時時間是2秒,假設2001端口過了3秒發數據,而2002端口無法服務,猜下結果會是什么呢?“兩個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, length 5
12:01:41.015121 IP 10.1.146.163.40678 > 10.1.146.133.2002: UDP, length 5
12:01:42.016103 IP 10.1.146.133.2001 > 10.1.146.163.40678: UDP, length 5
兩個請求應該使用不同的臨時端口收發,但從抓包結果看,客戶端雖然進行了兩次socket_create,但實際中卻使用了同一臨時端口(40678)收發數據!這就使得第二個請求收到了第一個請求的回包。
感覺上這應該算是個系統的BUG,從實驗中發現,此問題只在部分系統中存在,比如Linux內核2.6.32+php5.2.3就沒有此問題。
解決
每次指定socket端口,進行收發。如下面的紅色代碼所示。
$sock = socket_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的端口也有可能出現對撞,但畢竟這種機率不大,可以從很大程度上解決問題。
關鍵字:PHP、udp、端口
新文章:
- CentOS7下圖形配置網絡的方法
- CentOS 7如何添加刪除用戶
- 如何解決centos7雙系統后丟失windows啟動項
- CentOS單網卡如何批量添加不同IP段
- CentOS下iconv命令的介紹
- Centos7 SSH密鑰登陸及密碼密鑰雙重驗證詳解
- CentOS 7.1添加刪除用戶的方法
- CentOS查找/掃描局域網打印機IP講解
- CentOS7使用hostapd實現無AP模式的詳解
- su命令不能切換root的解決方法
- 解決VMware下CentOS7網絡重啟出錯
- 解決Centos7雙系統后丟失windows啟動項
- CentOS下如何避免文件覆蓋
- CentOS7和CentOS6系統有什么不同呢
- Centos 6.6默認iptable規則詳解