【问题标题】:php udp works only on loopbackphp udp 仅适用于环回
【发布时间】:2023-03-04 02:22:01
【问题描述】:

我正在尝试编写一个 php udp 客户端。

//Parsing values
error_reporting(E_ALL | E_STRICT);
ini_set("display_errors","1");

$cycles = $_GET['cycles'];
$cycles = $cycles > 600 ? 600 : $cycles;
if(!isset($_GET['lport']) || $_GET['lport'] < 1500 || $_GET['lport'] > 65534) {
    $rport = 11115;
} else {
    $rport = $_GET['lport'];
}
if(!isset($_GET['sport']) || $_GET['sport'] < 1500 || $_GET['sport'] > 65534) {
    $port = 11115;
} else {
    $port = $_GET['sport'];
}
$from = isset($_GET['ip']) ? $_GET['ip'] : '127.0.0.1';

//Relevant code starts here 
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($socket, '127.0.0.1', $rport);
socket_set_nonblock($socket);

while($cycles--) {
    $msg = "PING! " . $cycles;
    echo socket_sendto($socket, $msg, strlen($msg), 0, $from, $port) ? "sendto success<br>" : "sendto fail<br>";
    socket_recvfrom($socket, $buf, 1000, 0, $from, $port); //0x40 is MSG_DONTWAIT 
    echo "$from:$port - $buf<br>" . PHP_EOL;
    sleep(1);
}

socket_close($socket);

如果我用 ?cycles=10&ip=[external ip] 调用它,它不会工作,它会继续打印:

警告:socket_sendto() [function.socket-sendto]: 无法写入套接字 [22]: 中的无效参数 /var/www/default/Tests/UdpTest.php 在线 37
发送到 失败

警告: socket_recvfrom() [function.socket-recvfrom]: 无法从 [11] 接收:资源 暂时无法在 /var/www/default/Tests/UdpTest.php 上线 38
62.180.108.236:11116 -

如果我使用?cylces=10&amp;ip=127.0.0.1,它会按预期工作,接收它发送的内容。如果我使用两个不同的端口并尝试在该机器上运行 netcat,情况是一样的。外部 ip 是该机器的物理地址,脚本是从 apache 调用的,顺便说一句。

【问题讨论】:

  • 尝试将socket_bind从环回更改为服务器的外部IP地址。
  • 非常感谢,绑定到 0.0.0.0 也有效。 :)

标签: php sockets udp


【解决方案1】:

问题在于您要绑定的接口。

绑定到环回 (127.0.0.1) 意味着您只能与该网络接口上的设备进行通信。并且由于本地机器是该接口上的唯一设备,因此当给定另一个网络上的地址时,sendto()recvfrom() 将失败。

要解决此问题,请绑定到所有接口 (0.0.0.0) 或从服务器绑定到特定的外部 IP 地址。这将允许您与 IP 连接到的网络上的任何机器进行通信。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-06
    • 2014-05-16
    • 1970-01-01
    • 2016-04-20
    • 2014-12-09
    • 2012-04-20
    • 2018-03-04
    • 1970-01-01
    相关资源
    最近更新 更多