Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
188 views
in Technique[技术] by (71.8m points)

Java Socket Connection: receiving completely arbitrary integers from the Input Stream

I've been learning about sockets in Java to send information between two separate Java applications for a Minigame program I've been working on. The goal is to be able to have it so that Server A can tell Server B to do something by writing and reading ints in a switch statement. This is the code I have for the server-side socket:

@Override
public void run() {
    try (
            DataInputStream input = new DataInputStream(this.socket.getInputStream())
    ) {
        this.output = new DataOutputStream(this.socket.getOutputStream());
        while (!this.finished) {
            int type = input.readInt();
            this.plugin.getLogger().info("Type: " + type + " from " + this.socket.getRemoteSocketAddress());
            switch (type) {
                case 1: {
                    ServerManager.getInstance().addActiveServer(this.serverInfo, input.readInt());
                    break;
                }
                case 2: {
                    int length = input.readInt();
                    for (int i = 0; i < length; i++) {
                        UUID uuid = UUID.fromString(input.readUTF());
                        PlayerData playerData = PlayerManager.getInstance().getPlayerData(uuid);
                        if (playerData == null) {
                            continue;
                        }
                        playerData.setPlaying(false);
                        playerData.setSpectating(false);
                        playerData.setQueuing(false);
                        playerData.getPlayer().connect(this.plugin.getLobbyServer());
                    }
                    ServerManager.getInstance().addInactiveServer(this.serverInfo);
                    break;
                }
                case 3: {
                    int length = input.readInt();
                    for (int i = 0; i < length; i++) {
                        UUID uniqueId = UUID.fromString(input.readUTF());
                        PlayerData playerData = PlayerManager.getInstance().getPlayerData(uniqueId);
                        if (playerData == null) {
                            continue;
                        }
                        playerData.setQueuing(true);
                    }
                    break;
                }
                default:
            }
        }

        this.output.close();
        this.socket.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

When the Minigame begins the countdown sequence, it writes and flushes '1' to the server-side socket before writing and flushing '3' when the Minigame actually starts.

// Tells Server A that the max players have been met
// and to start a countdown sequence for a Minigame.
public void sendStartUpdate(int gameKey) {
    try {
        this.output.writeInt(1);
        this.output.writeInt(gameKey);
        this.output.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
// Lets Server A know that the player is queued up for a Minigame
public void sendQueuingUpdate(@NotNull Collection<UUID> players) throws IOException {
    this.output.writeInt(3);
    this.output.writeInt(players.size());
    for (UUID player : players) {
        this.output.writeUTF(String.valueOf(player));
    }
    this.output.flush();
}

However, for some reason, whenever I run the program, the server first receives '1' and '3' as expected, but then receives a series of really long integers from Server B out of nowhere.

[02:45:24 INFO] Type: 1                     // This is good!
[02:45:27 INFO] Type: 3                     // This is good!
[02:45:43 INFO] Type: 16777216              // Huh??
[02:45:43 INFO] Type: 1280                  // WHAT???
[02:45:43 INFO] Type: 256                   // Insert confused guy meme here
[02:45:43 INFO] Type: 610548020
[02:45:43 INFO] Type: 1667643705
[02:45:43 INFO] Type: 925721650
[02:45:43 INFO] Type: 842018100
[02:45:43 INFO] Type: 878785581
[02:45:43 INFO] Type: 1647785059
[02:45:43 INFO] Type: 761477426
[02:45:43 INFO] Type: 825570148
[02:45:43 INFO] Type: 1647851062

This issue also happens when the Minigame ends and the program notifies Server A that the Minigame has ended. I didn't have this problem until I made a slight modification to the code below:

public void sendPlayingUpdate(@NotNull Collection<UUID> players) throws IOException {
    this.output.writeBoolean(true);
    this.output.writeBoolean(false);
    this.output.writeBoolean(false);
    this.output.writeInt(5);
    this.output.writeInt(players.size());
    for (UUID player : players) {
        this.output.writeUTF(String.valueOf(player));
    }
//  this.output.writeInt(4);
//  this.output.writeInt(players.size());
//  for (UUID uuid : players) {
//      this.output.writeUTF(String.valueOf(uuid));
//  }
    this.output.flush();
}

The commented-out bit is the original code. If I replace it with the uncommented code, it gives all those arbitrarily large integers. Is there a way for another application to somehow connect to the same port as the socket and begin feeding random information? I just don't see how one small minor change can lead to something like 1667643705 being sent, the integers honestly remind me of hashcodes.

I appreciate anything.

question from:https://stackoverflow.com/questions/65661837/java-socket-connection-receiving-completely-arbitrary-integers-from-the-input-s

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The timestamps indicate a 16 second gap between the second and third packet. So it's likely not the second 3 packet that is corrupt. Somewhere else you are sending a malformed packet in code not presented.

The data is:

01 00 00 00  00 00 05 00  00 00 01 00  24 [... load of hex ...]

0x24 is $, but could be a string length from a writeUTF - say, the two UUIDs concatenated.

I would start off testing the parse code can interpret the output of the format code without all the server stuff. As a benefit, that will require factoring the code better.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...