Я работаю в сетевой системе 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.Как показано в приведенном выше коде, каждый пакет имеет свой собственный байтовый идентификатор.При тестировании я понял, что что-то не так, например, некоторые пакеты не принимаются правильно.
Возможно, что при чтении / записи пакетов на каналы остаются некоторые байты.Есть идеи?