PHP udp的錯(cuò)包問(wèn)題
添加時(shí)間:2014-12-30 19:36:41
添加:
思海網(wǎng)絡(luò)
問(wèn)題
看下面一段代碼
$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);
}
就是連續(xù)用UPD向兩個(gè)server收發(fā)數(shù)據(jù)(為說(shuō)明問(wèn)題,這里的server使用了最簡(jiǎn)單的回射邏輯),如果一切流程正常,客戶端會(huì)收到兩次‘HELLO’。但是,如果服務(wù)端出了問(wèn)題呢?目前,客戶端的超時(shí)時(shí)間是2秒,假設(shè)2001端口過(guò)了3秒發(fā)數(shù)據(jù),而2002端口無(wú)法服務(wù),猜下結(jié)果會(huì)是什么呢?“兩個(gè)NULL!”,直覺(jué)上應(yīng)該是這個(gè)答案。如果你也這么認(rèn)為,那么恭喜你,答錯(cuò)了。
實(shí)際的答案是:
NULL
string(5) "HELLO"
分析
使用tcpdump抓包,得到如下結(jié)果
(133為服務(wù)端,163為客戶端,客戶端php版本5.3.1,Linux內(nèi)核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
兩個(gè)請(qǐng)求應(yīng)該使用不同的臨時(shí)端口收發(fā),但從抓包結(jié)果看,客戶端雖然進(jìn)行了兩次socket_create,但實(shí)際中卻使用了同一臨時(shí)端口(40678)收發(fā)數(shù)據(jù)!這就使得第二個(gè)請(qǐng)求收到了第一個(gè)請(qǐng)求的回包。
感覺(jué)上這應(yīng)該算是個(gè)系統(tǒng)的BUG,從實(shí)驗(yàn)中發(fā)現(xiàn),此問(wèn)題只在部分系統(tǒng)中存在,比如Linux內(nèi)核2.6.32+php5.2.3就沒(méi)有此問(wèn)題。
解決
每次指定socket端口,進(jìn)行收發(fā)。如下面的紅色代碼所示。
$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));
當(dāng)然,rand的端口也有可能出現(xiàn)對(duì)撞,但畢竟這種機(jī)率不大,可以從很大程度上解決問(wèn)題。
關(guān)鍵字:PHP、udp、端口
新文章:
- CentOS7下圖形配置網(wǎng)絡(luò)的方法
- CentOS 7如何添加刪除用戶
- 如何解決centos7雙系統(tǒng)后丟失windows啟動(dòng)項(xiàng)
- CentOS單網(wǎng)卡如何批量添加不同IP段
- CentOS下iconv命令的介紹
- Centos7 SSH密鑰登陸及密碼密鑰雙重驗(yàn)證詳解
- CentOS 7.1添加刪除用戶的方法
- CentOS查找/掃描局域網(wǎng)打印機(jī)IP講解
- CentOS7使用hostapd實(shí)現(xiàn)無(wú)AP模式的詳解
- su命令不能切換root的解決方法
- 解決VMware下CentOS7網(wǎng)絡(luò)重啟出錯(cuò)
- 解決Centos7雙系統(tǒng)后丟失windows啟動(dòng)項(xiàng)
- CentOS下如何避免文件覆蓋
- CentOS7和CentOS6系統(tǒng)有什么不同呢
- Centos 6.6默認(rèn)iptable規(guī)則詳解