我创建了一个函数,可以让我查看 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;
}
你可能被文档搞糊涂了,实际上写错误只发生在socket关闭的时候,UDP并不关心数据是否发送成功。当端点返回所需的响应时,您可以确定端点工作正常。所以你应该使用
fread
并检查它的返回值。
if ($length === fwrite($udpConnection, $command, $length)) {
$result = fread($udpConnection, 128);
if(!empty($result) && $result == <desired response>)
$udp = true;
}