NIO буферы и каналы - PullRequest
       10

NIO буферы и каналы

0 голосов
/ 29 сентября 2018

Я работаю в сетевой системе TCP на базе NIO.Вот как выглядит стандартный пакет:

public final class KeepAlivePacket implements Packet {
    private static final ByteBuffer BUF = ByteBuffer.allocate(8);

    private long ping;

    @Override
    public void write(SocketChannel channel) {
        BUF.clear();
        BUF.putLong(System.nanoTime());
        BUF.flip();

        try {
            channel.write(BUF);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void read(SocketChannel channel) {
        BUF.rewind();

        try {
            channel.read(BUF);
        } catch (IOException e) {
            e.printStackTrace();
        }

        BUF.rewind();

        this.ping = TimeUnit.MILLISECONDS.convert(System.nanoTime() - BUF.getLong(), TimeUnit.NANOSECONDS);
    }

    public long getPing() {
        return this.ping;
    }
}

Этот код я использую для отправки и получения пакетов:

private final ByteBuffer writeBuffer = ByteBuffer.allocate(1);
private final ByteBuffer readBuffer = ByteBuffer.allocate(1);

public void send(Packet packet, SocketChannel channel) {
    Class<? extends Packet> packetType = packet.getClass();
    byte id = PacketRegistry.INSTANCE.getId(packetType);

    this.writeBuffer.clear();

    if (id != -1) {
        this.writeBuffer.put(id);
        this.writeBuffer.flip();

        try {
            channel.write(this.writeBuffer);
        } catch (IOException e) {
            e.printStackTrace();

            return;
        }

        packet.write(channel);

        for (ChannelOutboundHandler handler : this.outboundHandlers) {
            handler.packetSent(channel, packet);
        }
    }
}

public boolean receive(SocketChannel channel) {
    this.readBuffer.rewind();

    int bytesRead;

    try {
        bytesRead = channel.read(this.readBuffer);
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }

    if (bytesRead < 0) {
        return false;
    }

    if (bytesRead == 0) {
        return true;
    }

    this.readBuffer.rewind();

    byte identifier = this.readBuffer.get(0);

    if (PacketRegistry.INSTANCE.has(identifier)) {
        Class<? extends Packet> packetType = PacketRegistry.INSTANCE.getType(identifier);
        Packet packet;

        try {
            packet = this.instantiationStrategy.instantiate(packetType, channel);
        } catch (InstantiationException e) {
            e.printStackTrace();

            return true;
        }

        packet.read(channel);

        for (ChannelInboundHandler handler : this.inboundHandlers) {
            handler.packetReceived(channel, packet);
        }
    }

    return true;
}

По сути, каждый пакет имеет свой собственный ByteBuffer и пишет/ читает его на SocketChannel.Как показано в приведенном выше коде, каждый пакет имеет свой собственный байтовый идентификатор.При тестировании я понял, что что-то не так, например, некоторые пакеты не принимаются правильно.

Возможно, что при чтении / записи пакетов на каналы остаются некоторые байты.Есть идеи?

...