我的世界java服务器软件包,Java将握手数据包发送到Minecraft服务器

I have been working on a java program that basically acts like Minechat(text-based app to just view chat.) I have never really worked with networking too much, so the issue is figuring out how to send packets correctly. I am currently at the position of creating the handshake with the server. After hours of research, I have come up with the following code, but it always runs into the "Failed! (Exception)" message. To me, everything looks correct, but for all I know it could be 100% wrong. If someone could point out what I'm doing wrong here, I'd really appreciate it.

For reference, feel free to use this and 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)");

}

}

EDIT:

More research suggests I use a Byte array, but this confuses me on how to represent a string and using strings is required?

解决方案

Looking at this page http://wiki.vg/Protocol it looks like your not writing enough data nor in the right order. You also need to be using varint which is a special type of data representation of an integer.

Relevant links to this issue:

The status ping works as follows:

C->S : Handshake State=1

C->S : Request

S->C : Response

C->S : Ping

S->C : Pong

C is client and S is server

Using the wiki and the provided code samples I modified your code to follow the entire status request.

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;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值