How do I set up my sockets for this mpg in java?

Started by
5 comments, last by Sirisian 16 years, 8 months ago
So I have come to a point where I can move my Skeletal Animated char around on my mesh and everything is great. My nest move is to implement some server-client code, so that more players can log in and just walk around for starters. Im using LWJGL which is a Java binding for opengl made for developing games. Though I have implemented a 3d-engine with skeletal animation from scratch, I know close to nothing about now to implement some solid multiplayer server-client-code! I have read a bit here and there because I want to have a good base before i begin to work on it. I dont want to make alot of code and then having to change everything because i didnt do my homework, but ofcourse some changing code is inevitable. Well, here is what I plan to do: I will send an array of int/longs through to the server. The first int will tell the server what kind of action needs to be performed. Like 1 for moving. The following two ints would then be x and y coordinates. 2 could be speech and so on. First I tought about using object-streams, but then I read that serialization could make a bandwidth-problem and that I should avoid it if posible. Can I send through arrays and not having to serialize? What would be the best solution? If any on you guys have java code-snipets with posible solutions please post em. I dont know if this is a good plan, but feel free to tell me your oppinion. Also if some of you know some good articles I can read about this, please throw in a link. Thanks in advance!
Advertisement
Yes, you can send through integer arrays, or perhaps better byte arrays/streams.

If you just send the x/y coordinates to the server, and it echoes it to the other players, then you're opening yourself up for cheating, because a hacker can change the packets and send whatever x/y coordinates he wants. Thus, the server needs to validate all the commands that come in.

More information and general pointers to networking for games can be found in the Forum FAQ, although it's not particularly heavy on Java specifics.
enum Bool { True, False, FileNotFound };
Quote:First I tought about using object-streams, but then I read that serialization could make a bandwidth-problem and that I should avoid it if posible.


Don't worry about that. While java.io Serialization is bulky, it's not that wasteful, but it contains a lot of redundant information. Until you get everything running, use that - since it works.

And this is Java - send nicely structures classes through, not some obscure arrays. The lower level you introduce to your logic, the hard the optimization will become.

The default code is just something like this:
package com.mmo.network;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;import java.net.InetAddress;import java.net.Socket;public class ObjectEndpoint {    private Socket socket;    private ObjectOutputStream oos;        private class ReaderThread implements Runnable    {        private NetworkCallback callback;        private ObjectInputStream ois;                public ReaderThread( Socket s, NetworkCallback cb ) throws IOException        {            callback = cb;            ois = new ObjectInputStream(s.getInputStream());        }                public void run()         {            try {                while (true) {                    callback.handleObject( ois.readObject() );                }            } catch (Exception e ) {                // we're done            }            System.out.println("ReaderThread exiting...");        }    }        ObjectEndpoint( InetAddress address, int port, NetworkCallback cb ) throws IOException    {        socket = new Socket( address, port );        oos = new ObjectOutputStream( socket.getOutputStream() );        Thread t = new Thread( new ReaderThread( socket, cb ), "ObjectEndpoint ReaderThread");        t.start();    }    public void send( Serializable o ) throws IOException    {        oos.writeObject( o );        oos.flush();    }}


Unfortunately, this isn't suitable for handling client, since it implies one thread per socket - that's also required because readObject blocks until all data is available.

To get around this limitation, look into NIO. Then, rather than sending data to the socket stream directly, send a short containing serialized object's length, then bytes following that. Do this without serialization. When you then receive entire serialized form, use readObject to instantiate the whole thing.

NIO structures should allow you to minimize allocations during the process. And if you can enforce threads sending the data, then you can re-use the send buffer as well.
Quote:Original post by Antheus
Don't worry about that. While java.io Serialization is bulky, it's not that wasteful, but it contains a lot of redundant information. Until you get everything running, use that - since it works.


Agreed, but ...

Quote:
And this is Java - send nicely structures classes through, not some obscure arrays. The lower level you introduce to your logic, the hard the optimization will become.


Ugh, no. Send objects for now (as above), but plan on stopping as soon as you can. Network data should ALWAYS be low-level - there is practically nothing about a high-level language's data-structures that you want for a wire protocol. Use the right tool for the job - send custom data structures over the wire.

On a related note, one of the (few) great advantages of network programming is that it's totally language and OS independent - until you force it to be otherwise :).
Quote:Original post by redmilamber
Ugh, no. Send objects for now (as above), but plan on stopping as soon as you can. Network data should ALWAYS be low-level - there is practically nothing about a high-level language's data-structures that you want for a wire protocol. Use the right tool for the job - send custom data structures over the wire.

On a related note, one of the (few) great advantages of network programming is that it's totally language and OS independent - until you force it to be otherwise :).


What I meant was, serialization is done at lowest level possible. Application should use and know only of objects.

The penalty for creation of objects in Java is much smaller than in C++ (for example). While it may make sense to bring network buffers directly to highest possible level to defer de-serialization, and possibly allow for some reduced work while reading the packet, possibly through stack-based algorithms, in Java this penalty is irrelevant (either way you go, work will be the same, just coupling gets higher).

My point was, how you ultimately convert a high-level object into network stream is irrelevant, just don't bring this knowledge high up in the application. Due to generational garbage collection it would have adverse performance effects, since serialization would keep wrong objects alive for too long.
Quote:The penalty for creation of objects in Java is much smaller than in C++ (for example).


That's not actually true, as you will create more pressure on the garbage collector, which will globally slow down everything. In C++, with even a half-decent allocator, creating is a pointer increment and counter increment, and freeing is a list link and counter decrement.

Thus, in Java (and other garbage collected languages), it's even more important to hang on to objects and re-use them, rather than create them for convenience.
enum Bool { True, False, FileNotFound };
I just want to point out pooling objects with a garbage collecting language is the best. I pool all of my objects for like particles and everything that needs to be allocated frequently and the performance gain is noticeable.

This topic is closed to new replies.

Advertisement