You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用UDP套接字检测Minecraft基岩版服务器在线状态异常排查

问题分析与修复方案

你的函数始终返回true的核心原因是UDP协议的无连接特性,加上代码逻辑没有正确验证服务器的响应,具体问题点如下:

  • UDP套接字创建不代表服务器在线:fsockopen('udp://...') 只要本地系统能成功创建UDP套接字,就会返回资源对象,完全不检查目标服务器是否存在或可达。哪怕目标IP/端口是无效的,这个调用也大概率返回非false。
  • fwrite成功不代表服务器收到数据:UDP没有传输确认机制,fwrite 只是把数据写入本地操作系统的发送缓冲区,只要缓冲区有空间就会返回成功,和服务器是否在线、是否收到数据毫无关系。
  • 缺少响应校验逻辑:MCPE服务器的在线检测需要发送UNCONNECTED_PING包后,等待并验证服务器返回的UNCONNECTED_PONG包。你的代码只发了ping,完全没处理响应,直接判定在线。

修复后的代码示例

下面的代码会发送标准的MCPE无连接ping,并等待服务器的响应,只有收到符合格式的pong包才返回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'];
    }

    // 创建UDP套接字
    $socket = @socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
    if (!$socket) {
        return false;
    }

    // 设置超时(秒+微秒)
    socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, ['sec' => 2, 'usec' => 0]);

    // 构造MCPE无连接Ping包
    $OFFLINE_MESSAGE_DATA_ID = pack('c*', 0x00, 0xFF, 0xFF, 0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFD, 0xFD, 0x12, 0x34, 0x56, 0x78);
    $currentTime = time();
    $pingPacket = pack('cQ', 0x01, $currentTime); // ID_UNCONNECTED_PING + 64位时间戳
    $pingPacket .= $OFFLINE_MESSAGE_DATA_ID;
    $pingPacket .= pack('Q', 2); // 客户端GUID(随便填一个固定值就行)

    // 发送Ping包
    $sent = @socket_sendto($socket, $pingPacket, strlen($pingPacket), 0, $this->address, $this->port);
    if (!$sent) {
        socket_close($socket);
        return false;
    }

    // 接收服务器响应
    $buffer = '';
    $from = '';
    $port = 0;
    $bytesReceived = @socket_recvfrom($socket, $buffer, 1024, 0, $from, $port);
    
    if ($bytesReceived > 0) {
        // 验证响应是否为UNCONNECTED_PONG包
        if (ord($buffer[0]) === 0x1C) { // ID_UNCONNECTED_PONG
            // 解析时间戳,确认和发送的一致(可选校验)
            $receivedTime = unpack('Q', substr($buffer, 1, 8))[1];
            if ($receivedTime === $currentTime) {
                $udp = true;
            }
        }
    }

    socket_close($socket);
    return $udp;
}

关键修复点说明

  1. 改用socket扩展:相比fsockopen,PHP的socket扩展对UDP操作的控制更精准,能直接设置接收超时并处理数据包收发。
  2. 添加响应接收与校验:发送ping后等待服务器返回的pong包,校验包ID(0x1C)和时间戳,确保是目标服务器的有效响应。
  3. 正确处理超时:通过SO_RCVTIMEO设置接收超时,避免无限等待。

内容的提问来源于stack exchange,提问作者Thrallix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 16:23:20