Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (538)
Games in Android Showcase (132)
games submitted by our members
Games in WIP (600)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  KryoNet: TCP and UDP client/server NIO library  (Read 10728 times)
0 Members and 1 Guest are viewing this topic.
Offline Nate

« JGO Bitwise Duke »


Medals: 158
Projects: 4
Exp: 14 years


Esoteric Software


« Posted 2009-09-30 05:08:00 »

Project page:
http://code.google.com/p/kryonet/

Comments, criticism, questions, let me have it. Smiley

This project used to be called Ninja, but was renamed to KryoNet and the serialization portion extracted into a new project, Kryo:
http://www.java-gaming.org/topics/kryo-fast-efficient-java-serialization/21295/view.html

Offline Riven
« League of Dukes »

« JGO Overlord »


Medals: 840
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #1 - Posted 2009-09-30 05:40:44 »

Thanks for the backlink. That reminds me I should create one heck of a homepage... too!

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social
Offline princec

« JGO Spiffy Duke »


Medals: 429
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #2 - Posted 2009-09-30 06:26:46 »

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?

Cas Smiley

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Riven
« League of Dukes »

« JGO Overlord »


Medals: 840
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #3 - Posted 2009-09-30 07:48:49 »

If it's not obvious what a parameter does, like here:
1  
2  
3  
server.start(false);
client.start(false);
removeObject.setNonBlocking(true, true);


I'd suggest using enums:
1  
2  
3  
server.start(KryoThread.DAEMON);
client.start(KryoThread.NORMAL);
remoteObject.setNonBlocking(KryoBlocking.ASYNC, KryoInvoke.FIRE_AND_FORGET);





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.

Why does even Client have it's own Selector + Thread? Even connecting can be non-blocking.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social
Offline Nate

« JGO Bitwise Duke »


Medals: 158
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #4 - Posted 2009-09-30 09:03:01 »

Thanks for taking a look guys. Smiley

Thanks for the backlink. That reminds me I should create one heck of a homepage... too!
No problem. And thanks! Cheesy

I think that if an API can't be reasonably described on a single page, something's wrong!

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. Smiley Sorry I have no more links for this paragraph. Kiss

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?

I'd suggest using enums:
You're right, the enum is much clearer.

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!

Why does even Client have it's own Selector + Thread?
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.

Even connecting can be non-blocking.
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.

Offline princec

« JGO Spiffy Duke »


Medals: 429
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #5 - Posted 2009-09-30 14:34:16 »

Ah, right, if it's for the purposes of generating a unique integer ID code to uniquel represent a class then I understand why you're doing it.

Cas Smiley

Offline Nate

« JGO Bitwise Duke »


Medals: 158
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #6 - Posted 2010-04-21 09:23:03 »

Check out this robot that is powered by KryoNet!
http://www.youtube.com/watch?v=ZeZ3R38d3Cg
How freaking cool is that? Cheesy

Offline CommanderKeith
« Reply #7 - Posted 2010-04-21 10:37:42 »

Very cool! So where does KryoNet fit in to that? in the communication between the laptop and the android phone??

The robot reminds me of that movie with Bruce Willis (or maybe it's Stallone) vs those big police robots that shred people Smiley

Offline Nate

« JGO Bitwise Duke »


Medals: 158
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #8 - Posted 2010-04-21 11:05:13 »

Very cool! So where does KryoNet fit in to that? in the communication between the laptop and the android phone??

You got it!

Pretty neat idea to build a robot with an Android phone as the brain. Gives you a camera, wifi, accelerometer, etc. Apparently these robots shoot airsoft pellets and they fight them! Smiley

Offline h3ckboy

JGO Coder


Medals: 5



« Reply #9 - Posted 2010-04-21 13:15:46 »

haha, that is awesome Cheesy, I cant watch the video right now, but I definitely will when I get home.

I have one question, did u have anything to do witht hs, or did u just get nformed about ths?
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline arielsan
« Reply #10 - Posted 2010-04-21 19:17:38 »

really nice, I want one of those robots so I can assemble a nexus one with it!

Offline Cero
« Reply #11 - Posted 2012-09-22 14:44:50 »

I have a... performance related question I guess

the usual tutorials do this :
1  
if (object instanceof SomeRequest)


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

So instead of the above I do:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
if (object instanceof Message)
               {
                  Message request = (Message)object;
                 
                  System.out.println("("+connection.getRemoteAddressTCP()+"): "+request.data);
                 
                  Message response = new Message();
                 
                  if (request.data.toLowerCase().startsWith("join"))
                  {
                     System.out.println("Appears to be a join command");
                     response.data = "You have joined the Server !";
                  }
                  else if (request.data.toLowerCase().startsWith("echo"))
                  {
                     System.out.println("Appears to be an echo command");
                     response.data = "You are saying: "+request.data;
                  }
                  else
                  {
                     System.out.println("Unknown command");
                     response.data = "Shut up.";
                  }


Something like that. Of course it works... but what about performance ?
I do want the very best performance, especially for network stuff, so if this is somehow slower, I would refrain from using it...

Offline matheus23

JGO Kernel


Medals: 114
Projects: 3


You think about my Avatar right now!


« Reply #12 - Posted 2012-09-22 16:25:59 »

@Cero:
I'd do it different.

This is the Message class:
1  
2  
3  
public class Message {
    public byte message;
}


This is the Messages class:
1  
2  
3  
4  
5  
public class Messages {
    public static final byte JOIN = 0;
    public static final byte ECHO = 1;
    public static final byte ANYTING = 2; // Just an example of more stuff...
}


So then you'd test it like that:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
if (object instanceof Message) {
    Message msg = (Message) object;
    switch (msg.message) {
    case Messages.JOIN:
        // Whatever you want to do here...
        break;
    case Messages.ECHO:
        // Whatever you want to do here too...
        break;
    case Messages.ANYTHING:
        // Heh...
        break;
    default:
         // Something unkown happened here ?!?
         break;
    }
}


You could even use an enum for the Messages class I think... But It could be possible, that the performance isn't too good with that one then...

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline Cero
« Reply #13 - Posted 2012-09-22 16:31:54 »

yeah sure you could do it like that too

in my case, I already have a script language which I could just plug into here, which is why I ask about performance penalties.

but yeah enums alone would be slightly faster than strings

Offline Nate

« JGO Bitwise Duke »


Medals: 158
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #14 - Posted 2012-09-22 19:16:50 »

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.

Offline Cero
« Reply #15 - Posted 2012-09-22 20:44:16 »

Well in this case its all convenience aside... if the classes method is the fastest, I will use that.

Offline Nate

« JGO Bitwise Duke »


Medals: 158
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #16 - Posted 2012-09-23 05:47:09 »

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.

Offline OttoMeier

Senior Devvie


Medals: 4
Projects: 1



« Reply #17 - Posted 2012-09-23 10:52:39 »

Is there a way to get hashcode from kryo? (for manual Delta Compression)
Offline Nate

« JGO Bitwise Duke »


Medals: 158
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #18 - Posted 2012-09-24 03:49:04 »

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.

Offline OttoMeier

Senior Devvie


Medals: 4
Projects: 1



« Reply #19 - Posted 2012-10-06 18:45:00 »

indeed it was easy just in case anybody else need it:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
public class HashUtil {

   private static final ThreadLocal<Kryo> kryo = new ThreadLocal<Kryo>(){
      protected Kryo initialValue() {
         Kryo kryo = new Kryo();
         return kryo;
      };
   };
   
   public static int hash(Object object){
      Output output = new Output(1000);
      kryo.get().writeObject(output, object);
      int hashCode = Arrays.hashCode(output.toBytes());
      output.close();
      return hashCode;
   }

}
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

rwatson462 (28 views)
2014-12-15 09:26:44

Mr.CodeIt (19 views)
2014-12-14 19:50:38

BurntPizza (37 views)
2014-12-09 22:41:13

BurntPizza (72 views)
2014-12-08 04:46:31

JscottyBieshaar (34 views)
2014-12-05 12:39:02

SHC (46 views)
2014-12-03 16:27:13

CopyableCougar4 (42 views)
2014-11-29 21:32:03

toopeicgaming1999 (110 views)
2014-11-26 15:22:04

toopeicgaming1999 (96 views)
2014-11-26 15:20:36

toopeicgaming1999 (29 views)
2014-11-26 15:20:08
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
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
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!