The first thing I thought, right at the start of looking at how to use the API, was "why do I have to register a class to serialize it?" Would it not be better if it could auto-register unrecognised classes? Particularly those ones marked as Serializable?

The first thing I thought, right at the start of looking at how to use the API, was "why do I have to register a class to serialize it?" Would it not be better if it could auto-register unrecognised classes? Particularly those ones marked as Serializable?

Well, the quick answer is, making you register classes is easier for me. Registering means each class is given the same ID on both the server and clients. Only the ID needs to be sent across the wire.

Lesser reasons include... Registering means you have to think about what you are sending, and how it gets serialized. It provides a chance to optimize serialization by specifying things like "can never be null" or the type of items in an ArrayList. This is a bit of an extreme case of optimization, but could save a reasonable amount of bandwidth in some situations. Here is the (much cleaner) unoptimized class, and here is a chart showing the differences (8.4% in this case, could be more with different data). The optimization lets it beat protobuf in the benchmarks. Sorry I have no more links for this paragraph.

How would an auto-registration scheme work? I'm assuming what classes you want to send wouldn't be known until the first time they are sent. The first time a class is sent it'd be sent with an ID and the class name String. The receiving side would keep track of the remote mappings of ID to class and deserialization would have a lookup per object. It gets tricky if the first time a class is sent over UDP, since it isn't known if the other side will receive it.

This would be a reasonably complex orchestration for TCP and no clear solution for UDP, all just to avoid registration. What do you guys think?

For the start method, there could be a no-arg version that did the more popular option. I wonder if daemon or non-daemon is usually what people want? If they are using the method I assume they have a game thread, so daemon is probably fine.

The Connection.id is short which means it will easily overflow, and you can (and will, eventually!) end up with concurrent connections with the same id.

Overflow is ok, only -1 and 0 are special connection IDs. Thanks for pointing it out though, I wasn't handling the case of skipping -1 and 0. To completely wrap around and have two connections with the same IDs, a client would have to connect, and then 65,535 clients would have to connect before the first one disconnects. This doesn't seem very likely!

Hmm. I was assuming only a handful of Client instances would be needed at most for a single client. Usually only one is needed. Is there a use case were you would need more than a couple Client instances? I guess you could try to implement a P2P network, though KryoNet is specifically targeting client/server.

Originally I was doing non-blocking connects, but it got messy. I decided what I really was doing was a blocking connect anyway. After switching to blocking it made my code in that area so much simpler.

Thanks again for taking a look. The NIO stuff has all kinds of crazy corners, half of which I think I've forgotten immediately after figuring them out. The more eyes the better! I've also put a lot of effort into the API, so feedback on ease of use, discoverability, etc is highly appreciated.

For every request you have a little class, sometimes a class that doesnt even have fields.Fine.If I want for many reasons to do it differently:There is only one class which has a string, and what I do is sending script commands over TCP using this string

At least use equalsIgnoreCase instead of toLowerCase().equals. A switch on an int or enum will be much better, though I doubt this will be a performance bottleneck any time soon. A scripting language is usually not terribly fast, but probably fine enough.

That is an easy attitude to have, and honestly it can be fun to optimize, but it isn't necessary the most productive attitude. Switching on an enum or int will be the fastest, at the cost of 1-2 bytes to send the enum/int. Using separate classes with instanceof is slower, but convenient to have strongly typed messages. If that isn't needed, then a single class holding script as a string is totally reasonable. However, I very much doubt the difference between a switch and instanceof will make any noticeable difference. In such cases, choose the easiest to implement and/or read.

Not sure what you mean. You can put serialized bytes through Arrays.hashCode(byte[]). Kryo 1 had a delta compressor. It was removed in 2 as no one made use of it, but it could be resurrected. It remembers the last bytes sent and only sends the delta bytes using GDIFF.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org