ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2019-05-28 09:48:10  阅读:274  来源: 互联网

标签:java network-programming packets minecraft


我一直在研究一个基本上像Minechat(基于文本的应用程序,只是查看聊天)的java程序.我从来没有真正使用过网络,所以问题是弄清楚如何正确发送数据包.我目前处于与服务器创建握手的位置.经过几个小时的研究,我提出了以下代码,但它总是遇到“Failed!(Exception)”消息.对我而言,一切看起来都是正确的,但据我所知,这可能是100%错误的.如果有人能指出我在这里做错了什么,我真的很感激.

作为参考,请随意使用thisthis.

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)");
    }
}

编辑:
更多的研究表明我使用的是Byte数组,但这让我对如何表示字符串以及使用字符串感到困惑?

解决方法:

看看这个页面http://wiki.vg/Protocol看起来你没有写出足够的数据,也没有正确的顺序.您还需要使用varint,它是整数的特殊数据表示形式.

此问题的相关链接:

> Handshake Protocol
> Packet format
> Server Ping Explanation and Example(涉及握手)

状态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,network-programming,packets,minecraft
来源: https://codeday.me/bug/20190528/1170180.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有