使用socket发送UDP数据包查看在线状态

问题描述 投票:0回答:1

我创建了一个函数,可以让我查看 Minecraft 基岩 (MCPE) 服务器是否在线,据我所知,这些服务器在 UDP 协议上运行。

UDP 是一种无连接协议,这意味着在您实际读取或写入某些内容之前,它不会让您知道它是在线还是离线。

我创建了一个应该执行此操作的函数,尽管它似乎总是返回我的 udp 变量 true,表示它在线。

有谁知道这可能是什么原因吗?

/**
 * @return bool
 */
public function checkUDP(): bool
{
    $udp = false;

    if ($result = resolveSRV($this->address, $this->port, 'udp')) {
        $this->address = $result['address'];
        $this->port    = $result['port'];
    }

    $udpConnection = @fsockopen('udp://' . $this->address, $this->port, $errCode, $errMsg, 2);

    if ($udpConnection !== false) {
        $OFFLINE_MESSAGE_DATA_ID = pack('c*', 0x00, 0xFF, 0xFF, 0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFD, 0xFD, 0x12, 0x34, 0x56, 0x78);

        $command = pack('cQ', 0x01, time()); // DefaultMessageIDTypes::ID_UNCONNECTED_PING + 64bit current time
        $command .= $OFFLINE_MESSAGE_DATA_ID;
        $command .= pack('Q', 2); // 64bit guid
        $length = strlen($command);

        // Set a longer timeout
        stream_set_timeout($udpConnection, 2);

        if ($length === fwrite($udpConnection, $command, $length)) {
            $udp = true;
        }

        fclose($udpConnection);
    }

    return $udp;
}
php minecraft
1个回答
0
投票

你可能被文档搞糊涂了,实际上写错误只发生在socket关闭的时候,UDP并不关心数据是否发送成功。当端点返回所需的响应时,您可以确定端点工作正常。所以你应该使用

fread
并检查它的返回值。

if ($length === fwrite($udpConnection, $command, $length)) {
    $result = fread($udpConnection, 128);
    if(!empty($result) && $result == <desired response>)
        $udp = true;
}
© www.soinside.com 2019 - 2024. All rights reserved.