收到的数据包与 Minecraft 协议-wiki 数据包不匹配

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

我正在尝试为 Minecraft 编写一个代理,它应该拦截客户端和服务器之间发送的包。 我让代理正常工作,但我收到的数据包 ID 似乎与协议 wiki 中的数据包 ID 不匹配。

例如:如果玩家/实体移动,客户端应该向服务器发送this数据包(我认为)。 该数据包以 ID 开头:0x2C。当玩家移动时我得到的实际数据包是:1B 00 14 C0 11 76 EE 76 F6 9B C0 40 55 40 00 00 00 00 00 BF FD 0E DF A6 AD 79 0F 01,其数据包ID:(0x)1B。

另一个例子:如果玩家破坏了一个区块,客户端应该将 this 数据包发送到服务器(我认为)。 该数据包以 ID 开头:0x07。当玩家打破方块时,我收到的实际数据包是:03 00 2F 00,其数据包 ID 为 (0x)03。

我显然做错了什么,但我不确定这是否是因为我引用了错误的数据包,或者有一些数据包可以解密。请注意,我在离线模式下运行我的服务器,因此应该有来自 Microsoft/Mojang 的任何身份验证,因此没有加密。

对于任何想知道的人,这是我的代码:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;

public class MinecraftProxy {
    private static final String SERVER_HOST = "localhost";  // Replace with your actual server host
    private static final int SERVER_PORT = 25565;  // Replace with your actual server port

    public static void main(String[] args) throws IOException {
        ServerSocket proxyServerSocket = new ServerSocket(55555);  // Proxy server port

        while (true) {
            Socket clientSocket = proxyServerSocket.accept();
            Socket serverSocket = new Socket(SERVER_HOST, SERVER_PORT);

            // Create separate threads to handle client-to-server and server-to-client communication
            Thread clientToServerThread = new Thread(() -> copyStreams(clientSocket, serverSocket, "Client to Server"));
            Thread serverToClientThread = new Thread(() -> copyStreams(serverSocket, clientSocket, "Server to Client"));

            clientToServerThread.start();
            serverToClientThread.start();
        }
    }

    private static void copyStreams(Socket inputSocket, Socket outputSocket, String direction) {
        try {
            InputStream inputStream = inputSocket.getInputStream();
            OutputStream outputStream = outputSocket.getOutputStream();

            byte[] buffer = new byte[4096];
            int bytesRead;

            while ((bytesRead = inputStream.read(buffer)) != -1) {
                byte[] packet = Arrays.copyOf(buffer, bytesRead);

                // Print the packet being sent or received
                if (direction.equals("Client to Server")) {
                    System.out.println("Packet Sent: " + bytesToString(packet));
                } else {
                    // System.out.println("Packet Received: " + bytesToString(packet));
                }

                // Data is being received from inputSocket (client) and sent to outputSocket (server)
                outputStream.write(buffer, 0, bytesRead);
                outputStream.flush();
            }

            // Input stream closed, so close the output stream and sockets as well
            outputStream.close();
            inputSocket.close();
            outputSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static String bytesToString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString();
    }
}

编辑:拼写错误

巨大更新:

第一个字节似乎对应于数据包的其余长度。 由于某种原因,第二个字节将始终为 00。 第三个字节将是数据包 ID。

例如,我的第一个示例的第三个字节是:14。这对应于 this 数据包,其中确实包含玩家位置。唯一的区别是这个数据包是服务器绑定的而不是客户端绑定的。

我的第二个例子的第三个字节是:2F。这对应于 this 数据包,而不是破坏块的数据包。现在我想起来了,这更符合逻辑,因为当打破一个方块时,玩家会挥动它的手臂。当然,这里的数据包也是服务器绑定的而不是客户端绑定的。

当我说在这个项目上总共花费了 20 多个小时时,我并没有撒谎,所以我要感谢大家回答我的问题。特别是@Rogue 和@RealSkeptic 提供的答案帮助我进一步前进。

干杯!

java minecraft packet packet-sniffers packet-capture
1个回答
0
投票

第一个字节似乎对应于数据包的其余长度。由于某种原因,第二个字节将始终为 00。第三个字节将是数据包 ID。

例如,我的第一个示例的第三个字节是:14。这对应于确实包含玩家位置的数据包。唯一的区别是这个数据包是服务器绑定的而不是客户端绑定的。

我的第二个例子的第三个字节是:2F。这对应于该数据包而不是破坏块的数据包。现在我想起来了,这更符合逻辑,因为当打破一个方块时,玩家会挥动它的手臂。当然,这里的数据包也是服务器绑定的而不是客户端绑定的。

当我说在这个项目上总共花费了 20 多个小时时,我并没有撒谎,所以我要感谢大家回答我的问题。特别是@Rogue 和@RealSkeptic 提供的答案帮助我进一步前进。

干杯!

© www.soinside.com 2019 - 2024. All rights reserved.