java.nio.BufferOverflowException in StringSerializer

Hi,

I am trying to send a message from a server to a client using SpiderMonkey.

One of the messages involves passing the game state to the client. This game state is serialized as a string which is usually 32 KB in size, though there is no upper limit to how large it can get. However, when I try to send it, I get:

[java]java.nio.BufferOverflowException

at java.nio.DirectByteBuffer.put(Unknown Source)

at java.nio.ByteBuffer.put(Unknown Source)

at com.jme3.network.serializing.serializers.StringSerializer.writeObject(StringSerializer.java:91)

at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:135)

at com.jme3.network.serializing.Serializer.writeClassAndObject(Serializer.java:303)

at com.jme3.network.serializing.serializers.FieldSerializer.writeObject(FieldSerializer.java:137)

at com.jme3.network.serializing.Serializer.writeClassAndObject(Serializer.java:303)

at com.jme3.network.connection.TCPConnection.write(TCPConnection.java:345)

at com.jme3.network.connection.Connection.run(Connection.java:130)

at com.jme3.network.connection.ConnectionRunnable.run(ConnectionRunnable.java:86)

at java.lang.Thread.run(Unknown Source)[/java]



It seems that com.jme3.network.connection.TCPConnection’s writeBuffer is defined as

[java]writeBuffer = ByteBuffer.allocateDirect(16228);[/java]

How can I send bigger data than that? Do I chop it into multiple messages? Do I have to use streaming?

Well most persons dont send taht alrge objects, most networkcodes only updates values that changed instead of sending a full gamestate.



However

You could split it up

or you could serialize it on your own wich is probably up to size 10 smaller since the default serialisation is not size optimized

EmpirePhoenix said:
Well most persons dont send taht alrge objects, most networkcodes only updates values that changed instead of sending a full gamestate.

However
You could split it up
or you could serialize it on your own wich is probably up to size 10 smaller since the default serialisation is not size optimized

No, this is already using my own serialization to JSON+GZip :(

It's the message the client gets when it first connects to the server; it does need to know the full game state (from scratch) at that point, so that it can load the world.

You could still do that in multiple steps can’t you? I mean, your world is probably build up out of several types of objects. Just send an packet for each type of object and then reconstruct the gamestate on the client side from those.

I send the initial state in multiple object constructor messages for my own, meanwhile while this happens updates for non exisitng clientside objects are just ignored.

hhmmzz… that would mean one or more of those constructor messages is larger then the buffer size. What kind of data are you sending? Entire Nodes?

I think you got confused as to who sent “I send the initial state in multiple object constructor messages for my own, meanwhile while this happens updates for non exisitng clientside objects are just ignored.”, ractoc. Anyway, I will split the message, thanks~

Classid, position rotation and stuff that is object specific. everything directly in a binary protocoll



[java]package online.newhorizons.shared.messages;



import java.io.DataInput;

import java.io.DataOutputStream;

import java.io.IOException;

import java.util.HashMap;



import online.newhorizons.shared.network.BinarySerializeable;

import online.newhorizons.shared.network.basicmessages.ServerMessage;

import online.newhorizons.shared.network.client.Client;

import online.newhorizons.shared.network.server.Server;



public abstract class AEvents extends ServerMessage{

HashMap<Short,BinarySerializeable> storage = null;

private int networkid;



public AEvents() {

storage = new HashMap<Short,BinarySerializeable>();

}



public AEvents(int size) {

storage = new HashMap<Short,BinarySerializeable>(size);

}



public void AddValue(short key,BinarySerializeable value){

storage.put(key,value);

}



public HashMap<Short, BinarySerializeable> getStorage(){

return storage;

}



public int getNetworkid() {

return this.networkid;

}



public void setNetworkid(int networkid) {

this.networkid = networkid;

}



@Override

public void readData(DataInput readfrom) throws IOException {

networkid = readfrom.readInt();

short count = readfrom.readShort();

while(count > 0){

short key = readfrom.readShort();

BinarySerializeable object = Client.getObjectFromId(readfrom.readShort());

object.readData(readfrom);

storage.put(key,object);

count–;

}

}



@Override

public void writeData(DataOutputStream writeto) throws IOException {

writeto.writeInt(networkid);

writeto.writeShort(storage.size());

for (short key:storage.keySet()){

writeto.writeShort(key);

BinarySerializeable object = storage.get(key);

assert (object != null):"Failture in stored value";

int objectid = Server.getClassTableId(object);

writeto.writeShort(objectid);

object.writeData(writeto);

}

}

}

[/java]

This is the generic message for updates of any kind, the key is a event (like 1 is position 2 is rotation ect, binry serializeable is a interface taht specifies that the boecjt can write itself into a dataoutputstream and read itself from there.



The constructor for a object consists of the classid + one full update send reliable. Unreliable message sthat arrive before the boejct exist on client are ignored, reliable ones arriving later due to the streambased connection for the reliable messages.