SFNet (Simple Fast Networking)

Hi, I am Gleade. I decided to start learning Java over the last few months and am quite interested in developing online games.
So I decided to start working on a networking library that will allow me to send raw data over a network. I have tried several networking libraries
already and could only find libraries that sent serialized objects over the network which provided a bit too much of a header for my simple tasks.

SFNet (Simple Fast Networking)

A simple Java networking library for TCP (no UDP yet) server-client connections.

The main idea behind this library is to allow the user to create fast networked games.
I have been influenced by a number of libraries already available, but I couldn’t find one that allowed you to send raw data over a network.

Currently supports:

  • server-client connections
  • easy-to-use packet container
  • sending / receiving packets
  • SQL database connections with an easy to column class

Repository:

Example:

Main:


public static void main(String args[])
{
    System.out.println("Server.");
    ServerStarter.listen(1337);
    ServerStarter.addListener(new ExampleServerListener());
    ClientStarter.connect("127.0.0.1", 1337);
    ClientStarter.addListener(new ExampleClientListener());

    Packet testPacket = new Packet();
    testPacket.writebyte((byte)1);
    testPacket.writestring("Hello World!");
    ClientStarter.sendPacket(testPacket);
}

Client Listener


public class ExampleClientListener implements SocketListener
{

    @Override
    public void received(Packet packet)
    {
        // Get the message ID of the packet
        int messageId = packet.readbyte();

        switch(messageId)
        {
            // Receive a string based message from a player
            case 1:
                String message = packet.readstring();
                System.out.println("Client: " + message);
                break;

                // Receive a positional based messaage from the player
            case 2:
                int x = packet.readbyte();
                int y = packet.readbyte();
                System.out.println("Player position update - x: " + x + " y: " + y);
                break;
        }
    }

}

Server Listener


public class ExampleServerListener implements SocketListener
{

    @Override
    public void received(Packet packet)
    {
        int messageId = packet.readbyte();

        switch(messageId)
        {
            // Receive a string based message from a player
            case 1:
                String message = packet.readstring();
                System.out.println("Server: " + message);
                ServerStarter.sendGlobalPacket(packet);
                break;

                // Receive a positional based messaage from the player
            case 2:
                int x = packet.readbyte();
                int y = packet.readbyte();
                System.out.println(" Server Player position update - x: " + x + " y: " + y);
                break;
        }
    }

}

You can also send raw data with KryoNet and many other libraries. Just send an Byte-Array, this will give you 1 Byte of overhead per 1300 Bytes.
What you are doing manually

// Get the message ID of the packet
int messageId = packet.readbyte();

can be done automatically with object registration (which is where the Byte from above goes).

The fast part is also absent in your example, sending single packets for movement updates and that on TCP?!
This would already be deadly if done with UDP.
For it to be fast it would take a lot of inconvenience like writing your own serializer framework :stuck_out_tongue:

I don’t want to put this down, this is just my honest opinion.

I did look at KryoNet and found it to be a bit cluttered for my own personal liking. Being new to Java it confused me in several areas, maybe it was the lack of examples/documentation.

Would that be more efficient? I am curious.

The example was just an example. Of course sending x/y co-ords every update would be slow. This wasn’t an example of movement, it was an example of updating an objects position :slight_smile: But I do see your point. I should show a better example. Additionally the library only supports TCP currently.

You aren’t putting it down at all, infact, I wanted other peoples opinions just to see what you/others think. Thank you very much for your input, I appreciate you taking time to look over it.

[quote]Would that be more efficient? I am curious.
[/quote]
It is pretty efficient, you register a class on client and server, for example MovementUpdatePacket.class and the class gets an id (internally) that is represented by a variable byte length integer of 1 to 5 byte, but most likely one byte since you usually do not have thousands of different network message types.
This means that (in a real world scenario) per serialized object, one byte is used to differentiate between objects that are received and one byte is as low as you can go without bit-packing. (Your example also uses one byte for that btw :wink: )

Do I understand correctly that your concept is:

  • Create a Packet (represents UPD/TCP packet)
  • Fill the Packets ByteBuffer
  • Send it
  • The other side reads the bytes again

Your Packet class is both data and serialization, it would be cleaner to split that up into Packet and SerializerUtil to get rid of features that don’t belong in a data-structure.

Your Packet class has a major inefficiency: https://github.com/Gleade/SFNet/blob/master/SFNet/src/com/sfnet/utils/Packet.java#L122-L153

Why recreate the buffer each time you write a byte or short? Just create a buffer with a default size and then only have getBufferArray() return the necessary bytes.

You got it :slight_smile:

I will most likely take that approach on-board, thanks.

Okay cool, I did not know to do that. That sounds excellent. Thank you!