Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (487)
Games in Android Showcase (112)
games submitted by our members
Games in WIP (553)
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  
  How to compress data sent over the network?  (Read 1825 times)
0 Members and 1 Guest are viewing this topic.
Offline gcsaba2

Junior Member




Hello world


« Posted 2006-09-11 09:43:17 »

I'm thinking of making a simple protocol for communicating with the server through sockets. The messages would be something like this:

cmd=1;x=54;y=65;dir=2

So that would mean command=move, x, y, direction=north
Since this is text in Unicode I'm guessing this would be 21*8=168 bytes. Is there a way to make this less? Perhaps send it through a ZipOutputStream ? I've read somewhere that people use Huffman-coding for this?
Offline Kova

Senior Member





« Reply #1 - Posted 2006-09-11 11:46:00 »

why are you sending names also? why not just values if you know in wich order they will come?

I use NIO and ByteBuffer so I just send values, it takes space as much as actual primitives do (int and float 4B and so on) which is far less then with unicode (each char 16B).
Offline SluX

Junior Member





« Reply #2 - Posted 2006-09-11 12:06:47 »

U ve heard right. Huffman coding is used. It is not that hard to implement, we ve been experimenting with it on faculty...

"Intelligence is the most beautiful gift and the greatest temptation which one life can receive from the gods."Me Cheesy
Play strategic football
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline gcsaba2

Junior Member




Hello world


« Reply #3 - Posted 2006-09-11 12:10:26 »

OK storing all the coordinates in an int array is a good idea, I will do like that for most operations. Still, when sending the user name, password, or simple chat message to the server then probably Huffman coding is used. Or perhaps I should just get the byte[] from the String and send that?

Why do you use NIO? Is it because of the non-blocking IO, or it also has better performance?
Offline Kova

Senior Member





« Reply #4 - Posted 2006-09-11 12:23:42 »

It has better performance when you have many connections since it dosen't require multiple threads per single connection. Also I've find it to be quite logical but I can't really compare since I didn't used anything else. I don't know if you can use ByteBuffer directly without NIO (socket's channel) but you can surely write to buffer and send the data it contains by reading from it and then recreating ByteBuffer on other side when data arrives. It would be very bad to use Unicode if you're gonna store number values. For your message, if you don't have to parse it, that is you know the exact order of data, your message using ByteBuffer would be this:

154652

and it would be 1 byte for command (I assume you won't use over 256 commands), 2 bytes for x, 2 bytes for y (assuming these are screen coordinates so it won't surely go over 65k) and 1 byte for direction ... = 6 bytes total compared to your 168 bytes. Furthermore, those values probably can be compressed but I still haven't got to it in my game. Someone confirm that messages of primitives like this can be compressed?
Offline CaptainJester

JGO Knight


Medals: 12
Projects: 2
Exp: 14 years


Make it work; make it better.


« Reply #5 - Posted 2006-09-11 12:58:44 »

OK storing all the coordinates in an int array is a good idea, I will do like that for most operations. Still, when sending the user name, password, or simple chat message to the server then probably Huffman coding is used. Or perhaps I should just get the byte[] from the String and send that?

Stop worrying about trying to compress the data stream, unless you have to later on.  You will only be sending username and password when people log on, not during game play.  By running it through a compresser, the time saved with a smaller stream will be lost to the compression algorithm.  Especially if you are just starting out.  Just make it work.  Once you have it working, try it out and see if you really need to optimize your stream.

Offline gcsaba2

Junior Member




Hello world


« Reply #6 - Posted 2006-09-11 15:03:56 »

OK, so far I made the basic system. On the server side, I have a classical server with a blocking ServerSocket. When a player connects, I create a new thread for him and communicate through InputStream and OutputStream. There's no need for thread pooling, as I expect the number of players to be always less than 10.

On the client side I was using NIO and a non-blocking socket.
OK, so first of all, the client needs to log in by sending its user name and password. If this is ok, server personds with 0, otherwise 1.

I send the data like this:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
   public static boolean login(String userName, String password) throws IOException {
      ByteBuffer buf = ByteBuffer.allocate(256);
      buf.put(Command.LOGIN);
      String str = "u="+userName+";p="+password;
      buf.put(str.getBytes());
      socket.write(buf);
     
      buf.clear();
      socket.read(buf);
     
      if (buf.get(0) == Command.OK)
         return true;
      else
         return false;
   }


Command.LOGIN is a byte = 19

On the server side, I read the bytes into an array, then check the first byte for the command and proceed from there:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
   public void run() {
      while (running) {
         try {
            byte[] bytes = new byte[300];
            int i = 0;
            int n = -1;
            while (i < 256 && (n = input.read()) != -1) {
               bytes[i] = (byte)n;
               i++;
            }
           
            System.out.println("Received: " + bytes[0]);
           
            // first byte contains the command
           byte[] response = null;
            switch (bytes[0]) {
               case Command.LOGIN:
                  response = doLogin(bytes);
                  break;
               .....
            }
           
            output.write(response);
            output.flush();


As you can see, I always print out the command number I'm getting, so it should say that the command was 19. Instead, it always says:

Received: 0

Now, I checked it out, and if I connect to the server through telnet, and send 85 to it, then it will say that it has received 85, so obviously the problem is on the client's side.
When I send a number from the server's side (through OutputStream) the client will receive that number correctly.

Anyone can help me out what am I doing wrong?
Offline gcsaba2

Junior Member




Hello world


« Reply #7 - Posted 2006-09-11 15:52:27 »

OK figured it out. I needed to write

buf.flip()

before writing the buffer to the socket. It works now Smiley
Offline JAW

Senior Member


Medals: 2



« Reply #8 - Posted 2006-09-13 17:45:17 »

I wonder if you really need to optimize sending 200 bytes?
Using any network protocol like UPD or TCP will add quite some overhead, I wonder if you really improve performance when you reduce the data.

One way would be to send multiple information packages as one message. If you got 10 messages, send them as one, so you get nerwork overhead just once. I dont know how much TCP can pack, but if you cut the network protocol overhead by reducing the number TCP packages by 5 to 10 you will get far more out of it than by reducing your content by 50 byte.

I used google and a site says that a TCP package has about 50 bytes all in all that are transportet over the network. So you get extra 50 bytes with every message. Send 10 messages at once and you only get 5 byte extra per message. Only send information without names. Dont send x=10;y=20, just send 10;20.

Depending on how much you send:
- either optimisation is of no use because you do not send so much that it will get any reasonable faster
- or you send so much that compression and decompression might take too much performance and increase lantency

-JAW
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.

TehJavaDev (13 views)
2014-08-28 09:26:30

CopyableCougar4 (25 views)
2014-08-22 10:31:30

atombrot (38 views)
2014-08-19 00:29:53

Tekkerue (31 views)
2014-08-15 21:45:27

Tekkerue (32 views)
2014-08-15 21:22:17

Tekkerue (19 views)
2014-08-15 21:20:21

Tekkerue (29 views)
2014-08-15 21:12:11

Rayexar (66 views)
2014-08-10 17:49:23

BurntPizza (42 views)
2014-08-09 12:09:32

BurntPizza (34 views)
2014-08-07 17:01:56
List of Learning Resources
by Longor1996
2014-08-16 01:40:00

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

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

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

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

List of Learning Resources
by SilverTiger
2014-07-31 07:26:06

List of Learning Resources
by SilverTiger
2014-07-31 02:54:12

HotSpot Options
by dleskov
2014-07-07 16:59:08
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!