[OFFEN] Netty Packets mit ByteBufInputStream/ByteBufOutputStream

  • Hallo Dev-Tek Community,


    ich möchte schon seit einiger Zeit mit netty (5.0.0.Alpha2), ein "Packet System" mit ByteBufInputStreams bzw. ByteBufOutputStreams programmieren.

    Dazu habe ich mir bereits eine Abstrakte Klasse "Packet" angelegt:

    Jedoch funktioniert das Ganze nicht.

    Mein Server sieht wie folgt aus:

    Mein Client:


    Falls ihr mir sagen könnt, was ich noch verändern sollte bzw. was ich falsch mache, wäre ich euch sehr dankbar!


    Grüße, Linus E. | f4ls3


    P.S. Settings Klasse:

  • Dir fehlt in der Pipeline ein LengthDecoder und der ReadTimeoutHandler.

    Füg mal auf beiden Seiten diese Handler ein (vor deinen Handlern):

    Code
    channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30));
    // Decoding
    channel.pipeline().addLast("splitter", new LengthFieldBasedFrameDecoder(Short.MAX_VALUE, 0, 2, 0, 2));
    // Encoding
    channel.pipeline().addLast("prepender", new LengthFieldPrepender(2));


    Es wäre vielleicht auch ganz gut, wenn du uns sagst, was für einen Fehler du hast :)

  • Dir fehlt in der Pipeline ein LengthDecoder und der ReadTimeoutHandler.

    Füg mal auf beiden Seiten diese Handler ein (vor deinen Handlern):

    Code
    channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30));
    // Decoding
    channel.pipeline().addLast("splitter", new LengthFieldBasedFrameDecoder(Short.MAX_VALUE, 0, 2, 0, 2));
    // Encoding
    channel.pipeline().addLast("prepender", new LengthFieldPrepender(2));


    Es wäre vielleicht auch ganz gut, wenn du uns sagst, was für einen Fehler du hast :)

    Genau das ist das Problem, es gibt keine Fehlermeldung.


    Dir fehlt in der Pipeline ein LengthDecoder und der ReadTimeoutHandler.

    Füg mal auf beiden Seiten diese Handler ein (vor deinen Handlern):

    Code
    channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30));
    // Decoding
    channel.pipeline().addLast("splitter", new LengthFieldBasedFrameDecoder(Short.MAX_VALUE, 0, 2, 0, 2));
    // Encoding
    channel.pipeline().addLast("prepender", new LengthFieldPrepender(2));


    Es wäre vielleicht auch ganz gut, wenn du uns sagst, was für einen Fehler du hast :)

    Danke erstmal für die schnelle Antwort und deine Hilfe, aber jetzt bekomme ich im Server diese Fehlermeldung:

    und im Client diese:

    Code
    Feb 01, 2020 8:24:23 PM io.netty.channel.DefaultChannelPipeline$TailContext exceptionCaught
    WARNUNG: An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
    io.netty.handler.timeout.ReadTimeoutException


    Ich vermute es liegt daran, dass ich den ByteBuf im En- bzw. Decoder erst in einen ByteBufStream "umwandle" und dan erst die Id schreibe, aber ich kann mich auch irren.

  • f4ls3

    Hat den Titel des Themas von „Netty Packets mit ByteBufInputStream/ByteBufOutputStream“ zu „[OFFEN] Netty Packets mit ByteBufInputStream/ByteBufOutputStream“ geändert.
  • Ich glaube du hast es in der falschen Reihenfolge eingefügt.

    Bei dir am Server sollte es z.B. so aussehen:

  • Ich glaube du hast es in der falschen Reihenfolge eingefügt.

    Bei dir am Server sollte es z.B. so aussehen:

    Du hattest Recht, ich hab sie an die falsche Stelle geaddet, aber es kommen nach wie vor die selben Fehlermeldungen.


    Server:

    Client:


    Konsole (Server):

    Konsole (Client):

    Code
    08:48:43 01.02.2020 | INFORMATION: Connected to Server [localhost/127.0.0.1:5780/id=ea03c107].
    Feb 01, 2020 8:49:13 PM io.netty.channel.DefaultChannelPipeline$TailContext exceptionCaught
    WARNUNG: An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
    io.netty.handler.timeout.ReadTimeoutException
    Process finished with exit code 0
  • Dein Problem besteht darin, dass du nicht ganz das Prinzip eines Streams verstehst.

    Laut der Exception versuchst du einen Int zu lesen.

    Code
    Caused by: java.lang.IndexOutOfBoundsException
    at io.netty.buffer.EmptyByteBuf.readInt(EmptyByteBuf.java:470)
    at de.f4ls3.netty.server.SimpleServer$1$3.decode(SimpleServer.java:60)

    Das Problem ist nur, dass du einmal den Debug Int liest und einmal dann zur Bestimmung der PacketID. Nur verschiebst du damit den Reader Index, sodass du einmal deine korrekte Packet ID liest (in deinem System.out.println()) und das nächste .readInt() liest dann aber schon ein Teil deines Payloads ist. Das führt dazu, dass alles bei dir verschoben ist und du absolut nicht weißt, was Packet ID ist, was length, was payload, da der Buffer verschoben ist.

    Wenn du also ein Packet schreibst (z.B.)

    Code
    buf.writeInt(packet.id);
    buf.writeShort(s.length);
    buf.writeString(s);
    buf.writeBool(true);

    musst du das in genau der gleichen Reihenfolge lesen!


    Also:

    Code
    buf.readInt();
    buf.readShort();
    buf.readString();
    buf.readBool();


    Auch brauchst du ein Ping/Pong Packet, dass du manuell alle x Sekunden sendest, damit die ReadTimeoutException nicht geworfen wird, denn die tritt auf, wenn du x Sekunden nichts mehr gelesen hast.


    Ich weiß nicht wie sehr das hilft, aber ich kann dir vielleicht empfehlen einen Blick auf mein Minecraft-Server Network Code zu werfen:

    https://github.com/RecubeNET/R…ality/Recube.Core/Network & https://github.com/RecubeNET/R…nality/Recube.Api/Network

    (basic-functionality branch, weil da atm ein Bugfix drinne ist, der noch nicht gemerged geworden ist)

    Es sollte jedoch deinem Code ähneln, da ich dort auch für jedes Packet eine Klasse habe etc.