Как я могу добавить пакеты в Java? - PullRequest
1 голос
/ 25 мая 2019

У меня простая клиент-серверная система с Netty, и я отправляю данные с использованием пакетов.У 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() для воссоздания пакета на стороне сервера.

Кроме того, ByteBuf от Netty не может читать или писать собственные классы, насколько я знаю ...

Моя единственная идея - отправлять несколько пакетов, могу ли я этого избежать?

РЕДАКТИРОВАТЬ

Определение системы пакетной обработки, которую я использую.

Из-за плохо объясненной системы пакетной передачи я кратко расскажу, что этоделает:

Пакет в моем случае оборачивается вокруг ByteBufNetty единственный способ отправить данные - это записать их в 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.

То же самое происходит при декодировании, просто наоборот.

Надеюсь, это станет ясно.

Ответы [ 2 ]

1 голос
/ 25 мая 2019

Я бы не создавал классы Packet. Я бы просто использовал BufferedOutputStream для отправки данных вручную или ObjectOutputStream, если вы хотите отправить целые объекты. Вы также можете сообщить удаленному лицу о том, что вы отправляете (отправьте строку или что-либо еще, прежде чем добавлять данные).

, например

package com.stackoverflow.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.stackoverflow.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;
    }
}
0 голосов
/ 31 мая 2019

Я обнаружил, что проще всего присоединить пакет к другому, добавив переменную и несколько методов в класс, например:

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() вернуть, был ли пакет прикреплен или нет. getAttached() вернуть добавленный пакет.

В кодировщике вы проверяете, добавлен ли пакет, и если это так, просто вызывайте метод кодирования с добавленным пакетом. Как это:

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

То же самое для декодера и ваших пользовательских ChannelInboundHandler.

...