Java 缓冲区 - 无法发送长度大于 20kb 的对象
Java Buffer - Cannot send object with length bigger than 20kb
不知道为什么,不能发送长度大于20,000字节的对象。我喜欢缓冲区的长度小于剩余长度。我该如何解决?使用 Grizzly 和 Ambassador 库。虽然发送小值一切正常。
系统输出
- [05:44:04 信息]:14480
- [05:44:04 信息]:STOPED3 14480 < 20636
- [05:44:04 信息]:20557
- [05:44:04 信息]:STOPED2 20557 < 1229410144
我的代码:
private static final int HEADER_SIZE = 12;
@Override
public NextAction handleRead(final FilterChainContext ctx) throws IOException {
final Buffer buffer = ctx.getMessage();
System.out.println(buffer.limit());
final int total = buffer.remaining();
if (total < HEADER_SIZE) {
System.out.println("STOPED1 "+" "+total+" < "+HEADER_SIZE);
return ctx.getStopAction(buffer);
}
buffer.get();
buffer.get();
buffer.get();
buffer.get();
int len = buffer.getInt();
if (total < HEADER_SIZE + len) {
System.out.println("STOPED2 "+" "+total+" < "+(HEADER_SIZE+len));
return ctx.getStopAction(buffer);
}
byte[] pack = new byte[len];
buffer.get(pack);
String name = new String(pack);
int size = buffer.getInt();
final int completeMessageLength = HEADER_SIZE + size + len;
if (total < completeMessageLength) {
System.out.println("STOPED3 "+" "+total+" < "+completeMessageLength);
return ctx.getStopAction(buffer);
}
final Buffer remainder = total > completeMessageLength ? buffer.split(completeMessageLength) : null;
System.out.println("PACKET[IN] Name: " + name + " Size: " + total + " BodySize: " + buffer.remaining());
byte[] body = new byte[size];
buffer.get(body);
Packet packet = null;
try {
packet = getPacket(name);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if (packet == null) {
return ctx.getInvokeAction(remainder);
}
packet.read(body);
handlePacket(ctx.getConnection(), packet);
return ctx.getInvokeAction(remainder);
}
@Override
public NextAction handleWrite(final FilterChainContext ctx) throws IOException {
Packet packet = ctx.getMessage();
String name = packet.getClass().getName();
byte[] packetBody = name.getBytes();
byte[] body = packet.write();
int bodyLen = body.length;
int packetLen = packetBody.length;
final MemoryManager memoryManager = ctx.getConnection().getTransport().getMemoryManager();
int size = HEADER_SIZE + bodyLen + packetLen;
final Buffer output = memoryManager.allocate(size);
output.allowBufferDispose(true);
output.put((byte) 0);
output.put((byte) 0);
output.put((byte) 0);
output.put((byte) 0);
output.putInt(packetLen);
output.put(packetBody);
output.putInt(bodyLen);
output.put(body);
ctx.setMessage(output.flip());
System.out.println("PACKET[OUT] ID: " + name + " Size: " + size);
return ctx.getInvokeAction();
}
protected static Packet getPacket(String name) throws IllegalAccessException {
try {
Class cl = Class.forName(name);
return (Packet) cl.newInstance();
} catch (ClassNotFoundException | InstantiationException e) {
e.printStackTrace();
}
return null;
}
protected abstract void handlePacket(Connection connection, Packet packet);
在你上面的代码中,当条件为假时,你不会撤回 buffer
位置:if (total < HEADER_SIZE + len)
或 if (total < completeMessageLength)
。我认为你应该 mark()
在你从 bufffer
读取任何内容之前的位置,然后,如果 buffer
不完整,你应该 reset()
该位置,以便 handleRead()
方法可以读取数据header下次正确。
我猜,当发送数据小于20000字节时,发送数据不会拆分成不同的数据包,所以handleRead()
每次都会读取完整字节,但会拆分成发送数据量大时有多个数据包,所以handleRead()
可能会读取一部分发送数据。
不知道为什么,不能发送长度大于20,000字节的对象。我喜欢缓冲区的长度小于剩余长度。我该如何解决?使用 Grizzly 和 Ambassador 库。虽然发送小值一切正常。
系统输出
- [05:44:04 信息]:14480
- [05:44:04 信息]:STOPED3 14480 < 20636
- [05:44:04 信息]:20557
- [05:44:04 信息]:STOPED2 20557 < 1229410144
我的代码:
private static final int HEADER_SIZE = 12;
@Override
public NextAction handleRead(final FilterChainContext ctx) throws IOException {
final Buffer buffer = ctx.getMessage();
System.out.println(buffer.limit());
final int total = buffer.remaining();
if (total < HEADER_SIZE) {
System.out.println("STOPED1 "+" "+total+" < "+HEADER_SIZE);
return ctx.getStopAction(buffer);
}
buffer.get();
buffer.get();
buffer.get();
buffer.get();
int len = buffer.getInt();
if (total < HEADER_SIZE + len) {
System.out.println("STOPED2 "+" "+total+" < "+(HEADER_SIZE+len));
return ctx.getStopAction(buffer);
}
byte[] pack = new byte[len];
buffer.get(pack);
String name = new String(pack);
int size = buffer.getInt();
final int completeMessageLength = HEADER_SIZE + size + len;
if (total < completeMessageLength) {
System.out.println("STOPED3 "+" "+total+" < "+completeMessageLength);
return ctx.getStopAction(buffer);
}
final Buffer remainder = total > completeMessageLength ? buffer.split(completeMessageLength) : null;
System.out.println("PACKET[IN] Name: " + name + " Size: " + total + " BodySize: " + buffer.remaining());
byte[] body = new byte[size];
buffer.get(body);
Packet packet = null;
try {
packet = getPacket(name);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if (packet == null) {
return ctx.getInvokeAction(remainder);
}
packet.read(body);
handlePacket(ctx.getConnection(), packet);
return ctx.getInvokeAction(remainder);
}
@Override
public NextAction handleWrite(final FilterChainContext ctx) throws IOException {
Packet packet = ctx.getMessage();
String name = packet.getClass().getName();
byte[] packetBody = name.getBytes();
byte[] body = packet.write();
int bodyLen = body.length;
int packetLen = packetBody.length;
final MemoryManager memoryManager = ctx.getConnection().getTransport().getMemoryManager();
int size = HEADER_SIZE + bodyLen + packetLen;
final Buffer output = memoryManager.allocate(size);
output.allowBufferDispose(true);
output.put((byte) 0);
output.put((byte) 0);
output.put((byte) 0);
output.put((byte) 0);
output.putInt(packetLen);
output.put(packetBody);
output.putInt(bodyLen);
output.put(body);
ctx.setMessage(output.flip());
System.out.println("PACKET[OUT] ID: " + name + " Size: " + size);
return ctx.getInvokeAction();
}
protected static Packet getPacket(String name) throws IllegalAccessException {
try {
Class cl = Class.forName(name);
return (Packet) cl.newInstance();
} catch (ClassNotFoundException | InstantiationException e) {
e.printStackTrace();
}
return null;
}
protected abstract void handlePacket(Connection connection, Packet packet);
在你上面的代码中,当条件为假时,你不会撤回 buffer
位置:if (total < HEADER_SIZE + len)
或 if (total < completeMessageLength)
。我认为你应该 mark()
在你从 bufffer
读取任何内容之前的位置,然后,如果 buffer
不完整,你应该 reset()
该位置,以便 handleRead()
方法可以读取数据header下次正确。
我猜,当发送数据小于20000字节时,发送数据不会拆分成不同的数据包,所以handleRead()
每次都会读取完整字节,但会拆分成发送数据量大时有多个数据包,所以handleRead()
可能会读取一部分发送数据。