项目中经常用到PHP用UDP调用C++服务,我们这边的PHP 请求方法封装如下,一直没有问题出现,今天接入新的服务出现了问题
public static function request($reqBuffer,$host,$port)
{
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
//设置发送数据超时时间
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array("sec" => 0, "usec" => 500000));
//设置接收数据超时时间
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500000));
if (socket_connect($socket, $host, $port) === false) {
socket_close($socket);
throw new Exception('connect server error'.socket_strerror(socket_last_error()), 100);
}
if (socket_write($socket, $reqBuffer, strlen($reqBuffer)) === false) {
socket_close($socket);
throw new Exception('send request error'.socket_strerror(socket_last_error()), 100);
}
if (($rspBuffer = socket_read($socket, 65536)) === false) {
socket_close($socket);
throw new Exception('receive response error'.socket_strerror(socket_last_error()), 100);
}
socket_close($socket);
return $rspBuffer;
}
问题如下:
socket_read 一直返回false 错误信息:Resource temporarily unavailable,而用tcpdump抓包显示C++服务已经回报,抓包数据如下:
[img]http://dl2.iteye.com/upload/attachment/0104/2638/834b4d13-7d6b-3b69-ae93-3caaffc87370.png[/img]
ICMP回报表示C++服务 230 发送的UDP包没有程序socket_read没有接收
这就是问题tcpdump显示数据已经发送 但是socket_read显示Resource temporarily unavailable
后来测试正常的请求才发现 ,服务器发送数据的端口从11188 变成成了11177 ,下面是可以收到的抓包
[img]http://dl2.iteye.com/upload/attachment/0104/2640/a3a866b9-dc8e-3048-9b97-0f94af92c357.png[/img]
后来发现socket_read不能接收端口变化的数据,适合与TCP这种保持连接,整个过程端口不变化的socket,而socket_recvfrom可以处理这种情况
然后函数封装换成了下面的方式:
public static functionrequest($reqBuffer, $host, $port)
{
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
//设置发送数据超时时间
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array("sec" => 0, "usec" => 500000));
//设置接收数据超时时间
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500000));
if (socket_sendto($socket,$reqBuffer, strlen($reqBuffer),0,$host,$port) === false) {
socket_close($socket);
throw new Exception('send request errorr' . socket_strerror(socket_last_error()), 100);
}
$from = "";
$port = 0;
if (socket_recvfrom($socket, $rspBuffer, 65536, 0, $from, $port) === false) {
socket_close($socket);
throw new Exception('receive response error' . socket_strerror(socket_last_error()), 100);
}
socket_close($socket);
return $rspBuffer;
}
现在OK了 不在会用ICMP回报未接收到数据
[img]http://dl2.iteye.com/upload/attachment/0104/2642/d67022b8-4505-3f87-81f5-da348518204a.png[/img]