Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 2 of 2

Thread: Ways of Transferring Data

  1. #1
    Junior Member
    Join Date
    May 2011
    Posts
    12
    Thanks
    0
    Thanked 4 Times in 4 Posts

    Default Ways of Transferring Data

    Let me start of with an introduction. My name is Zyle. I have been programming with Java since late 2006. It would be safe to say that I've programmed more than 4 hours a day since then. I am currently attending a university for Software Development and Software Application Technology. I wouldn't say that I know a lot, but I certainly have experience with Java, as well as other popular languages.

    Now that you know a little bit about me, let's get to the good stuff. I am currently trying to create a simple way for transmitting data in a client-server model. I have used the standard java.net classes in the past, and have recently been working with NIO. I have used MINA and Netty, and while they both have their pros/cons, I'd prefer to write my own library. I have asked this question in another community (not specifically focused on Java), and got different answers. However I though that I'd post here to see what your opinions are. (Note that the data transferred will be using the TCP, not UDP)

    Currently, I am thinking about having 5 classes.
    1. Packet - Pretty simple, just a class to hold data being transmitted to the client/server.
    2. Client - Just a class to represent a client connected to the server.
      public class Client {
          private final SocketChannel channel_;
       
          protected Client(SocketChannel channel) {
              channel_ = channel;
          }
       
          public final SocketChannel getChannel() {
              return channel_;
          }
      }
    3. PacketDecoder - Again pretty simple. I'm thinking that it should look something like
      public interface PacketDecoder {
          public Packet decode(Client client, ByteBuffer buffer);
      }
      Basically what it will do is convert some data from a ByteBuffer into a usable Packet object.
    4. PacketHandler - These classes will be what perform the logic for the packet.
      public interface PacketHandler {
          public void handle(Client client, Packet packet);
      }
    5. PacketEncoder - These classes will turn a Packet object into a ByteBuffer which can be written directly to the client/server.
      public interface PacketEncoder {
          public ByteBuffer encode(Client client, Packet packet);
      }


    Note that this is just a brief summary of how I see it. Now that you have all the background information, here are my questions:
    1. What are any/all improvements you can suggest for this design?
    2. How should I be handling Packets? Should each packet have its own class? Should I have the size of each packet predetermined, or have the length in the first 1-2 bytes before the data?
    3. If each Packet were its own class, how would I handle the PacketEncoder? If I have all the data hard-coded into the PacketEncoder, then I end up with an enormous switch statement. If I were to add a
      public ByteBuffer getData();
      method to the Packet class, then wouldn't that defeat the purpose of the PacketEncoder?


    I had more questions but neglected to write them down. I'll add them to the list when I can remember them.

    Thank you for reading my thread, if you have any information that might be of assistance, I would be grateful for your response.


  2. #2
    Super Moderator Json's Avatar
    Join Date
    Jul 2009
    Location
    Warrington, United Kingdom
    Posts
    1,274
    My Mood
    Happy
    Thanks
    70
    Thanked 156 Times in 152 Posts

    Default Re: Ways of Transferring Data

    Hello there Zyle,

    I would really consider using a library already available out there, maybe MINA and Netty aren't to your liking but it's well worth it not having to deal with all of the network stuff. I would suggest you have a look at KryoNet which is a networking library built on top of the Kryo Serialization Library. It offers really nice ways of sending POJO's across the wire.

    However if you still insist on writing your own, I'd say you're on the right track, the important thing I'd say is the encoder/decoder of packets. If the first byte in the packet bytearray defines what type of packet you're dealing with the decoder will easily know how to decode it (what things to read and in what order).

    In all fairness, Packet could be an interface with a read method and a write method. You would also need a way of registering your classes.

    For instance your Packet.java interface could look like this:

    import java.nio.ByteBuffer;
     
    public interface Packet {
     
        public void encode(final ByteBuffer byteBuffer);
     
        public void decode(final ByteBuffer byteBuffer);
    }

    And you could have a packet implementation like this:

    import java.nio.ByteBuffer;
     
    public class SimplePacket implements Packet {
     
        private int someInteger;
     
        private float someFloat;
     
        @Override
        public void encode(final ByteBuffer byteBuffer) {
            byteBuffer.putInt(this.someInteger);
            byteBuffer.putFloat(someFloat);
        }
     
        @Override
        public void decode(final ByteBuffer byteBuffer) {
            this.someInteger = byteBuffer.getInt();
            this.someFloat = byteBuffer.getFloat();
        }
     
        // Setters and getters here
    }

    Then you might need some sort of converter or similar to translate packets and bytebuffers:

    import java.nio.ByteBuffer;
    import java.util.HashMap;
    import java.util.Map;
     
    public class PacketConverter {
     
        private static Map<Integer, Class<? extends Packet>> packetClasses = new HashMap<Integer, Class<? extends Packet>>();
     
        public synchronized static void registerClass(final Class<? extends Packet> packetClass) {
            final int id = packetClasses.size() + 1;
            packetClasses.put(id, packetClass);
        }
     
        private int getIdForPacketInstance(final Packet packet) {
            for (final Map.Entry<Integer, Class<? extends Packet>> entry : packetClasses.entrySet()) {
                if (entry.getValue().getName().equals(packet.getClass().getName())) {
                    return entry.getKey();
                }
            }
     
            return -1;
        }
     
        public ByteBuffer serialize(final Packet packet) {
            final int id = getIdForPacketInstance(packet);
     
            if (id != -1) {
                final ByteBuffer byteBuffer = ByteBuffer.allocate(Integer.MAX_VALUE);
                byteBuffer.putInt(getIdForPacketInstance(packet));
                packet.encode(byteBuffer);
                byteBuffer.flip();
     
                return byteBuffer;
            }
     
            return null;
        }
     
        public Packet deserialize(final ByteBuffer byteBuffer) throws Exception {
            final int packetId = byteBuffer.getInt();
            final Class<? extends Packet> packetClass = packetClasses.get(packetId);
     
            if (packetClass != null) {
                final Packet packet = packetClass.newInstance();
                packet.decode(byteBuffer);
     
                return packet;
            }
     
            return null;
        }
    }

    As you can see the PacketConverter allows you to register packet classes. This model is really similar to the KryoNet model which is why I would suggest you have a look at that first since that would take care of the object serialization for you, sparing you from dealing with the bytebuffers.

    Also note that I've not tested this code so there might be issues.

    Hope this helps you in some way.


    Daniel

Similar Threads

  1. 500 Ways to Print 1 to 10
    By Freaky Chris in forum The Cafe
    Replies: 132
    Last Post: August 1st, 2014, 06:47 AM
  2. Transferring elements between arraylists
    By KipTheFury in forum Collections and Generics
    Replies: 6
    Last Post: August 23rd, 2010, 02:13 PM
  3. Trying 3 different ways to do the same thing, each one is wrong
    By shemer77 in forum What's Wrong With My Code?
    Replies: 14
    Last Post: June 4th, 2010, 07:01 PM
  4. any ways to run a class from another class?
    By javanub:( in forum Java Theory & Questions
    Replies: 3
    Last Post: May 9th, 2010, 06:57 AM
  5. Java program to encrypt an image using crypto package
    By vikas in forum Java Networking
    Replies: 1
    Last Post: July 7th, 2009, 11:00 AM