udp的错包问题
看下面一段代码
$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
{
$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的端口也有可能出现对撞,但毕竟这种机率不大,可以从很大程度上解决问题。
如果有更好的解决办法,欢迎大家交流~
�0�2
�0�2
上一篇: linux解压tar文件命令是什么
推荐阅读
-
js闭包引起的事件注册问题介绍
-
关于Tar包压缩时相对路径的问题探讨
-
Windows 64 位 mysql 5.7以上版本包解压中没有data目录和my-default.ini及服务无法启动的快速解决办法(问题小结)
-
VPS 服务器时间不准确造成的lnmp一键安装包安装失败问题
-
解决PyCharm import torch包失败的问题
-
解决Ubuntu pip 安装 mysql-python包出错的问题
-
安装SQL Server 2016出错提示:需要安装oracle JRE7 更新 51(64位)或更高版本问题的解决方法
-
【Unity】关于UDP 客户端不能先给服务器发消息的问题
-
浅谈JavaScript中的作用域和闭包问题
-
详解闭包解决jQuery中AJAX的外部变量问题