我正在基于NIO的TCP网络系统上工作。 这是标准数据包的样子:
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上写入/读取它。如上面的代码所示,每个数据包都有自己的字节标识符。测试时,我意识到有些问题,例如某些数据包未正确接收。
一种可能是,当数据包在通道上读/写时,剩余一些字节。有什么想法吗?