当前位置: 首页 > 面试题库 >

Java将握手数据包发送到Minecraft服务器

蔺霄
2023-03-14
问题内容

我一直在研究一个Java程序,该程序基本上类似于Minechat(基于文本的应用程序,仅用于查看聊天。)我从来没有真正与网络打交道,因此,问题在于弄清楚如何正确发送数据包。我目前处于与服务器创建握手的位置。经过数小时的研究,我提出了以下代码,但始终会遇到“
Failed!(Exception)”消息。对我来说,一切看起来都是正确的,但就我所知,这可能是100%错误的。如果有人可以指出我在这里做错了什么,我将非常感激。

供参考,请随时使用this和this。

public static void main(String[] args) throws IOException {
    host = new InetSocketAddress("162.244.165.111", 48040);
    socket = new Socket();
    System.out.println("Connecting...");
    socket.connect(host, 3000);
    System.out.println("Done!");
    System.out.println("Making streams...");
    output = new DataOutputStream(socket.getOutputStream());
    input = new DataInputStream(socket.getInputStream());
    System.out.println("Done!");
    System.out.println("Attempting handshake... "+host.getAddress().toString().substring(1));
    byte[] msg = ("47;"+host.getAddress().toString().substring(1)+";"+host.getPort()+";2;").getBytes(Charset.forName("UTF-16"));
    output.writeInt(msg.length+Integer.valueOf(0x00));
    output.writeByte(0x00);
    output.write(msg);
    output.flush();
    try {
        if (input.readByte() != 0x02)
            System.out.println("Failed!");
        else
            System.out.println("Done!");
    } catch (EOFException e) {
        System.out.println("Failed! (Exception)");
    }
}

编辑:更多研究建议我使用字节数组,但这使我困惑于如何表示字符串,并且需要使用字符串吗?


问题答案:

查看此页面http://wiki.vg/Protocol,看来您未写入足够的数据或顺序不正确。您还需要使用varint,它是整数的一种特殊类型的数据表示形式。

与该问题有关的链接:

  • 握手协议
  • 封包格式
  • 服务器Ping解释和示例(涉及握手)

状态ping的工作方式如下:

C->S : Handshake State=1
C->S : Request
S->C : Response
C->S : Ping
S->C : Pong

C是客户端,S是服务器

使用Wiki和提供的代码示例,我修改了您的代码以遵循整个状态请求。

public static void main(String [] args) throws IOException {
    String address = "162.244.165.111";
    int port = 48040;

    InetSocketAddress host = new InetSocketAddress(address, port);
    Socket socket = new Socket();
    System.out.println("Connecting...");
    socket.connect(host, 3000);
    System.out.println("Done!");
    System.out.println("Making streams...");
    DataOutputStream output = new DataOutputStream(socket.getOutputStream());
    DataInputStream input = new DataInputStream(socket.getInputStream());

    System.out.println("Done!");
    System.out.println("Attempting handshake... "+host.getAddress().toString());


    byte [] handshakeMessage = createHandshakeMessage(address, port);

    // C->S : Handshake State=1
    // send packet length and packet
    writeVarInt(output, handshakeMessage.length);
    output.write(handshakeMessage);

    // C->S : Request
    output.writeByte(0x01); //size is only 1
    output.writeByte(0x00); //packet id for ping


    // S->C : Response
    int size = readVarInt(input);
    int packetId = readVarInt(input);

    if (packetId == -1) {
        throw new IOException("Premature end of stream.");
    }

    if (packetId != 0x00) { //we want a status response
        throw new IOException("Invalid packetID");
    }
    int length = readVarInt(input); //length of json string

    if (length == -1) {
        throw new IOException("Premature end of stream.");
    }

    if (length == 0) {
        throw new IOException("Invalid string length.");
    }

    byte[] in = new byte[length];
    input.readFully(in);  //read json string
    String json = new String(in);


    // C->S : Ping
    long now = System.currentTimeMillis();
    output.writeByte(0x09); //size of packet
    output.writeByte(0x01); //0x01 for ping
    output.writeLong(now); //time!?

    // S->C : Pong
    readVarInt(input);
    packetId = readVarInt(input);
    if (packetId == -1) {
        throw new IOException("Premature end of stream.");
    }

    if (packetId != 0x01) {
        throw new IOException("Invalid packetID");
    }
    long pingtime = input.readLong(); //read response


    // print out server info
    System.out.println(json);

    System.out.println("Done!");
}

public static byte [] createHandshakeMessage(String host, int port) throws IOException {
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();

    DataOutputStream handshake = new DataOutputStream(buffer);
    handshake.writeByte(0x00); //packet id for handshake
    writeVarInt(handshake, 4); //protocol version
    writeString(handshake, host, StandardCharsets.UTF_8);
    handshake.writeShort(port); //port
    writeVarInt(handshake, 1); //state (1 for handshake)

    return buffer.toByteArray();
}

public static void writeString(DataOutputStream out, String string, Charset charset) throws IOException {
    byte [] bytes = string.getBytes(charset);
    writeVarInt(out, bytes.length);
    out.write(bytes);
}

public static void writeVarInt(DataOutputStream out, int paramInt) throws IOException {
    while (true) {
        if ((paramInt & 0xFFFFFF80) == 0) {
          out.writeByte(paramInt);
          return;
        }

        out.writeByte(paramInt & 0x7F | 0x80);
        paramInt >>>= 7;
    }
}

public static int readVarInt(DataInputStream in) throws IOException {
    int i = 0;
    int j = 0;
    while (true) {
        int k = in.readByte();
        i |= (k & 0x7F) << j++ * 7;
        if (j > 5) throw new RuntimeException("VarInt too big");
        if ((k & 0x80) != 128) break;
    }
    return i;
}


 类似资料:
  • 我一直在开发一个java程序,基本上类似于Minechat(基于文本的应用程序,用于查看聊天。)我从来没有在网络方面做过太多工作,所以问题是如何正确发送数据包。我目前正在创建与服务器的握手。经过几个小时的研究,我终于想出了以下代码,但它总是会出现“失败!(异常)”的消息。对我来说,一切看起来都是正确的,但据我所知,它可能是100%错误的。如果有人能指出我做错了什么,我会非常感激。 作为参考,请随意

  • 数据包格式的来源:http://wiki.vg/Protocol 我正试图用php编写一个程序,将数据包发送到我托管的minecraft服务器。这可能适用于不支持相同API格式的手机的多人游戏实现。我下面的代码是我失败的尝试。我怎样才能正确地做到这一点?服务器正在识别某些内容,但它要么没有发送任何内容,要么是其他内容。下面应该发送0x00,即握手数据包,以使用下一个状态ID:1请求服务器上的统计信

  • 我试图为minecraft服务器制作客户机/机器人,以自动保护聊天和禁止垃圾邮件发送者。(第一个成就) 我在这里找到了一些文档,并从这里实现了数据类型(所以它们看起来像这样--我还没有完成)。现在,我正在尝试发送inital数据包,应该如下所示: *fails表示bukkit服务器在控制台中输出以下内容,套接字关闭: 11:09:45[信息]/127.0.0.1:51256失去连接 我现在可以看到

  • 我一直在做这个项目,其中一个部分包括从Raspberry向我的服务器发送一些数据。但它不能正常工作,我不知道为什么。我试图通过删除“urllib2”并使用“request”来修复错误。但徒劳的是,一切都没有改变。如果有人能帮助我,我会非常感激的。谢谢! PHP代码: python代码:

  • 问题内容: 我在通过Notification从服务向活动发送数据时遇到问题,我单击了一个活动被调用的通知,但是当我尝试通过捆绑包添加一些参数时,我无法获得所谓的intent中的参数,我经历了链接 如何将通知单击中的参数发送到活动? 但是仍然没有运气。 其他人也发生过同样的问题吗? 提前致谢。 问题答案: 您还必须修改清单文件。 这是有效的示例: 这些变量和方法是Service类的成员: 这是Mai

  • 我们有一个场景,(UDP客户端程序)向(UP服务器)发送UDP数据包 TCP在数据通信开始之前和结束之后执行握手。UDP没有。 那么,运行在上的应用程序失败的原因是否是上的服务器程序没有准备好(关闭)接收UDP数据包?