Sending an array from server to client

I’ve implemented a fully working client and server application. They can communicate through messages. I also learned how to use broadcastmessages.



But now I’m wondering if anyone could provide me with a sample where you send a java object (in my case an array) from the server to the client. I have no idea what classes or methods I should use for this.

I was thinking about that method as well. But that’s the reason I made this post, just to see if it is possible to send entire objects.

Perhaps it’s a bad solution, but I made a chat program long time ago (not with jMonkey) and I sent Strings like “this:is:kinda:an:array” from the server then i used String.split(":"); at the client. But if you want to send entire objects that method wont work.

I remember that there was some java class that could do that. Else there is possible to do with SpiderMonkey.



A quick search give me this, looks pretty interesting: http://www.javaworld.com/javaworld/javatips/jw-javatip40.html

Ah damnit I posted this in the wrong section. Didn’t see there was a spidermonkey forum. Anyway I’m using spidermonkey for my network code.

Just put it in the message?



[java]class MyMsg extends AbstractMessage {

MyObject[] someArray;

}[/java]

Momoko_Fan is right. SpiderMonkey supports arrays just fine. No reason to use any tricks… just use it. :slight_smile:

Thanks will try it out :slight_smile:

I tried to send a 32x32x32 byte array, but I got a bufferoverflow exception. the array is around 43 KB so I don’t think that’s to much to send over a network with spidermonkey… Or is it?



[java]SEVERE: Unhandled error, endpoint:NioEndpoint[1, java.nio.channels.SocketChannel[connected local=/127.0.0.1:5050 remote=/127.0.0.1:51125]], context:network.messages.EnterGameMessage@152e961

java.nio.BufferOverflowException

at java.nio.Buffer.nextPutIndex(Buffer.java:495)

at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:145)

at com.jme3.network.serializing.serializers.ByteSerializer.writeObject(ByteSerializer.java:52)

at com.jme3.network.serializing.serializers.ArraySerializer.writeArray(ArraySerializer.java:125)

at com.jme3.network.serializing.serializers.ArraySerializer.writeArray(ArraySerializer.java:123)

at com.jme3.network.serializing.serializers.ArraySerializer.writeArray(ArraySerializer.java:123)

at com.jme3.network.serializing.serializers.ArraySerializer.writeObject(ArraySerializer.java:110)

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

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

at com.jme3.network.base.MessageProtocol.messageToBuffer(MessageProtocol.java:74)

at com.jme3.network.base.DefaultServer.broadcast(DefaultServer.java:157)

at com.jme3.network.base.DefaultServer.broadcast(DefaultServer.java:152)

at network.ServerListener.messageReceived(ServerListener.java:183)

at network.ServerListener.messageReceived(ServerListener.java:36)

at com.jme3.network.base.MessageListenerRegistry.messageReceived(MessageListenerRegistry.java:72)

at com.jme3.network.base.DefaultServer.dispatch(DefaultServer.java:221)

at com.jme3.network.base.DefaultServer$Redispatch.messageReceived(DefaultServer.java:470)

at com.jme3.network.base.DefaultServer$Redispatch.messageReceived(DefaultServer.java:466)

at com.jme3.network.base.KernelAdapter.dispatch(KernelAdapter.java:163)

at com.jme3.network.base.KernelAdapter.createAndDispatch(KernelAdapter.java:217)

at com.jme3.network.base.KernelAdapter.run(KernelAdapter.java:260)[/java]

That is too much for one data package. Try organizing your data in a different way? Why do you have to send such a big array anyway? You are not by any chance making a minecraft clone and are trying to store all data in a big array that describes the world? If thats the case, this approach is flawed as you waste way too much space for “tiles” that are not containing any data (think of the inside of mountains, the air etc). Instead of an array, think more like a class that has a getTile(x,y,z) method and generates the tile data on the fly from a database or similar. That database would e.g. only contain actual structures and their location and fills the “Tile” object with that info when that tile is requested. When no data is on that location, you return an empty Tile. This way you don’t store like hundreds of thousands of empty tiles. Having such a system you can also package smaller data sets to send over the network with just changes to the actual data.

I think SpiderMonkey’s packet limit is something like 65k but it might actually be 32k. I’d have to look at the code to be sure.



In any case, that’s a lot of data to try to send at once… you are better off breaking it up somehow.

Well I kinda really need all the data in the array… Except for the 0’s maybe but I can filter those out and just add them on the client side before drawing my terrain.



The 65 or 32k is that kilobyte or kilobit?



I’m thinking of sending pieces of my 32x32x32 array per packet?

If those are bytes then it might fit. shorts or ints, no way. In Mythruna, I run length encode my world tiles to send them and still have to break them up into parts for the really complex ones.



Pretty sure SM max message size (including the protocol overhead) is 65,536 bytes.

…and it was much smaller in old SM.

Had a quick glance at the run length encoding and it’s a pretty smart way to go at it. So run the run length encoding onto your world data and then just send a string to the client side. On the client side it then just gets reconstructed back to an array(in my case), right?

Yeah, I wrote special input/output streams to do the RLE for me… and then I actually gzip the final buffer for further shrinking. And then I have the ability to break a tile up into multiple messages if it’s still too big.