如何在 Java 中附加数据包?

How can I append packets in Java?

我用 Netty 构建了一个简单的 client/server 系统,我使用数据包发送数据。 在我的例子中,Packet 有两种写入和读取 BytBuf 的方法。 例如,包含字符串的数据包从字符串中获取字节并将它们写入 ByteBuf,然后发送,或者它从 ByteBuf 读取字节并创建消息。 这是我的数据包接口中的代码片段:

import io.netty.buffer.ByteBuf;

public abstract class Packet {

    public abstract void read(ByteBuf byteBuf);

    public abstract void write(ByteBuf byteBuf);
}

首先,当收到一个数据包时,我想检查是否有附加的数据包,然后我想访问或读取它。

问题在于接收数据包时的实例化。我可以将第二个数据包附加到另一个数据包并将其存储在第一个数据包的局部变量中,但是当我使用 Class.newInstance() 在服务器端重新创建数据包时它就消失了。

据我所知,Netty 的 ByteBuf 也无法读取或写入自己的 类...

我唯一的想法是发送多个包裹,我可以避免吗?

编辑

我使用的分组系统的定义。

由于没有很好地解释数据包系统,我将简要介绍它的作用:

在我的案例中,一个数据包包裹在 ByteBuf 周围。在 Netty 中,发送数据的唯一方法是以字节的形式写入 ByteBuf 中。基于字符串的数据包的示例是:

package com.sxf.protocol.chat.util.packets;

import io.netty.buffer.ByteBuf;

public class MessagePacket extends Packet {

    private String msg;

    public MessagePacket() {}

    public MessagePacket(String message) {
        this.msg = message;
    }

    @Override
    public void read(ByteBuf byteBuf) {
        byte[] msgBytes = new byte[byteBuf.readInt()];
        byteBuf.readBytes(msgBytes);

        msg = new String(msgBytes);
    }

    @Override
    public void write(ByteBuf byteBuf) {
        byte[] msgBytes = msg.getBytes();

        byteBuf.writeInt(msgBytes.length);
        byteBuf.writeBytes(msgBytes);
    }

    public String getMsg() {
        return msg;
    }
}

当您创建 Packet 时,您必须以 String 的形式添加消息。在编码过程中,我调用 write() 并传递通过管道发送的 ByteBuf 。然后将消息形成字节并写入 ByteBuf.

同样的情况发生在解码中,只是反过来。

我希望它能这么清楚。

我不会创建数据包 类。如果您想发送整个对象,我只会使用 BufferedOutputStream 手动发送数据或使用 ObjectOutputStream 。您还可以通知远程您发送的内容(在附加数据之前发送字符串或其他任何内容)。

例如

package com.Whosebug.q56304773;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;

public class PacketSender {
    private OutputStream networkStream;
    public void sendObject(Object o,String objInfo) throws IOException {
        try(BufferedOutputStream out=new BufferedOutputStream(getNetworkStream());
                ObjectOutputStream objectSender=new ObjectOutputStream(out);
                PrintWriter infoWriter=new PrintWriter(out)){
            infoWriter.printf("Object:%s", objInfo);
            objectSender.writeObject(o);
        }
    }
    public OutputStream getNetworkStream() {
        return networkStream;
    }
    public void setNetworkStream(OutputStream networkStream) {
        this.networkStream = networkStream;
    }
}


package com.Whosebug.q56304773;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;

public class PacketResciever {
    private InputStream networkStream;
    public void resv() throws IOException, ClassNotFoundException {
        try(BufferedInputStream in=new BufferedInputStream(getNetworkStream());
                BufferedReader infoReader=new BufferedReader(new InputStreamReader(in))){
            String header=infoReader.readLine();
            String[] splitted=header.split(":");
            switch(splitted[0]) {
                case "Object":
                    handleObject(new ObjectInputStream(in).readObject(),splitted[1]);
                    break;
                //other cases
            }

        }
    }
    private void handleObject(Object readObject,String info) {
        //search for handler and execute it
    }
    public InputStream getNetworkStream() {
        return networkStream;
    }
    public void setNetworkStream(InputStream networkStream) {
        this.networkStream = networkStream;
    }
}

我发现一个简单的方法是将一个数据包附加到另一个数据包,方法是向 class 添加一个变量和一些方法,如下所示:

package com.sxf.protocol.chat.util.packets;

import io.netty.buffer.ByteBuf;

public abstract class Packet {

    private Packet attached;

    public abstract void read(ByteBuf byteBuf);

    public abstract void write(ByteBuf byteBuf);

    public final boolean isLinked() {
        return attached != null;
    }

    public final void append(Packet packet) {
        attached = packet;
    }

    public final Packet getAttached() {
        if (isLinked()) {
            return attached;
        }

        throw new NullPointerException("unsafe access to getAttached");
    }
}

使用 append() 可以添加数据包并存储传递的数据包。 isLinked() return 是否附加了数据包。 getAttached() return 附加数据包。

在编码器中,您检查是否添加了数据包,如果是,只需调用添加数据包的 encode-method。像这样:

    if (packet.isLinked()) {
            out.writeBoolean(true);
            encode(ctx, packet.getAttached(), out);
    } else {
            out.writeBoolean(false);
    }

解码器和您的自定义相同 ChannelInboundHandler