【问题标题】:PHP Packets to a minecraft server?PHP 数据包到我的世界服务器?
【发布时间】:2014-01-16 23:26:34
【问题描述】:

数据包格式来源:http://wiki.vg/Protocol

我正在尝试用 php 编写一个程序,它将数据包发送到我托管的 minecraft 服务器。这可能适用于不支持相同 API 格式的手机的多人游戏实现。我下面的代码是我失败的尝试使这项工作。我怎样才能正确地做到这一点?服务器正在识别某些东西,但它要么没有发回任何东西,要么是什么东西。下面应该发送 0x00,即握手包以使用下一个状态 ID 请求服务器上的统计信息: 1. Minecraft 应该使用相同的 ID 进行响应,但使用服务器 motd 和玩家计数。对于 1.7.2,这将用于,它还将发送一个 server-icon.png。但我可以放心地忽略这些数据,因为它只是直接连接。

我做错了什么,我该如何解决?

Main.php

require("socket.php");

$f = getStat("zontreck.dyndns.biz",25565);
/*$za = 0x00;
$za[0] = 74;
$za[1] = "zontreck.dyndns.biz";
$za[2] = 25565;
$za[3] = 1;
*/
$za = array(0x00,"Protocol Version"=>73,
    "Server Address"=>"zontreck.dyndns.biz",
    "Server Port"=>25565,
    "Next State"=>1);
$dd = doWrite(pack("a",$za),$f);
echo("Response from doWrite: " .$dd."\n");
echo("Sending: " . pack("a",$za)."\n");
/*if(doWrite(pack("a",$za),$f))
{
    echo(fgets($f));
} else {
    echo(fgets($f));
}*/

$ff = fgets($f);
//$u = unpack("a",$ff);
fclose($f);
echo("Data from server: " . $ff."\n");
echo("Data from server length: " . strlen($ff)."\n");
//fclose($f);
?>

socket.php

<?

function getStat($url = "",$port=25565)
{
    $f = fsockopen($url,$port);
    return $f;
}

function doWrite($packet,$socket)
{
    return fwrite($socket,$packet);
}


?>

main.php 的输出

root@zontreck:/var/www/slmc# php main.php
PHP Notice:  Array to string conversion in /var/www/slmc/main.php on line 16
Response from doWrite: 1
PHP Notice:  Array to string conversion in /var/www/slmc/main.php on line 18
Sending: A
Data from server: 
Data from server length: 0
root@zontreck:/var/www/slmc# 

【问题讨论】:

  • Pack 需要一个 STRING,而您正在推入一个数组。你不能这样做。由于您在字符串上下文中使用数组,因此您正在打包文字词 Array 。由于您的包格式只是a,因此您正在打包传入字符串的单个字符。您希望 a* 接受无限数量的数据字符
  • 好吧,那我应该用什么来代替数组呢?我把“a”改成了“a*”。
  • 阅读协议文档会有所帮助:wiki.vg/Pocket_Minecraft_Protocol#Types 您需要准确地构建命令/握手数据包,而不仅仅是将一些数据放入数组中并希望一切正常。

标签: php sockets network-protocols minecraft packets


【解决方案1】:

您可能想看看这个: https://forums.bukkit.org/threads/web-php-simple-to-use-minecraft-server-status-query.144329/

这基本上是对这个库的一些解释,它完全符合你的要求: https://github.com/FunnyItsElmo/PHP-Minecraft-Server-Status-Query

它还使用套接字,因此您可以随时获取一些代码并根据需要对其进行修改,但我强烈建议您按原样使用该库,因为它可以完成您想要完成的工作。

【讨论】:

    【解决方案2】:

    两位评论者都是对的,你需要重新审视你是如何做到这一点的。

    更具体地说,Minecraft 协议使用 UDP,这意味着您需要使用 socket_create - http://php.net/manual/en/function.socket-create.php 访问原始套接字

    然后您需要构建一个string,其中包含正确的所有必需数据包,如@Marc B 所述。然后您可以将该字符串写入套接字。请注意,由于 UDP 既是无状态的,也没有纠错功能,因此如果返回错误,您还必须编写重试例程。

    您目前正在做的是用一种语言 (PHP) 构建数据结构,然后尝试将它们写入有线协议(完全不同),这几乎是不可能的。

    在 PHP 中当然可以做到这一点,但您必须在比现在低得多的水平上工作,使用原始套接字、十六进制数据字符串和网络错误处理。我建议您查看其他处理 UDP 数据的 PHP 库,看看是否有一些代码可以重用。

    socket_create 页面 cmets 中有一些您可以使用/学习的代码。特别是,您可以修改一个 TFTP 示例。

    不是一个简单的答案,但这在任何语言中都不是微不足道的,而且 PHP 并不是真正为此设计的,所以没有很多示例。

    【讨论】:

    • Minecraft 的协议是 TCP,而不是 UDP。您链接的是 Minecraft Pocket Edition 的协议规范,它确实使用了 UDP。
    猜你喜欢
    • 1970-01-01
    • 2020-09-03
    • 1970-01-01
    • 2019-03-25
    • 1970-01-01
    • 2021-07-09
    • 1970-01-01
    • 2021-07-24
    • 2019-02-03
    相关资源
    最近更新 更多