Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm working on creating a multiplayer game, with the client in ActionScript and the server written in Java. I'm using XMLSocket in the client to connect to the server. The server code looks something like:

ServerSocket server = new ServerSocket(port);

while(true)
{
    Socket client = server.accept();
    ClientHandlingProcess child = new ClientHandlingProcess(client);
    child.start(); // starts new thread for client
}

The client handling process looks something like:

while(true)
{
    byte[] arr = new byte[1024];
    if(socket.getInputStream().read(arr) == -1)
    {
        break;
    }

    handleInputMethod(arr);

    while(!message_queue.isEmpty())
    {
        socket.getOutputStream().write(message_queue.get(0).getBytes());
        message_queue.remove(0);
    }
}

The issue is that the read method is blocking, meaning I can't send any data while I'm waiting for data to come in. What would be a good way to fix this? Have two processes: one for reading and one for writing, have the client send empty requests when it has no proper messages to send, or is there another way I can proceed?

share|improve this question
    
The main takeaway from the below answers is that you should steer away from one (or more) thread per client, for scaleability reasons. Even today's most powerful quad core processors can only technically handle 8 simultaneous threads (four cores, two threads per core via hyperthreading); any more than that and there is an overhead for context switching between threads; essentially the processor juggling more threads than it can physically handle. Instead, look into non-blocking IO e.g. via Java's NIO library, or a 3rd party library. –  Ricket Apr 26 '11 at 4:03
add comment

4 Answers 4

You have basically these two options:

  • Use blocking IO with one reading thread per client
  • Use non blocking IO

The first option has the disadvantage that it does not scale for large number of clients.

While non blocking IO can be done by checking inputstream.available(), it may be a good idea to look at the New I/O API. Wikipedia has a good article on NIO with sample code. You can find additional information in the JavaDoc for the NIO package. And on a quick glance this tutorial seems helpful.

You might get away with doing smart things on the client side, such as sending a dummy message on every "turn". This, however, means that a rouge client can freeze your server. So you should not go into this direction.

share|improve this answer
    
He is already using blocking IO with one thread per client. –  Ricket Apr 25 '11 at 17:36
    
@Ricket, added the word "reading" before "thread per client". –  Hendrik Brummermann Apr 25 '11 at 17:40
add comment

Never rely on a client to do ANYTHING to make your server run properly. If you do, then malicious users can attack your game simply by refusing to perform whatever is required of them.

Use non-blocking IO or threads for this task. Threads is fine if you have a small number of players (eg, < 10) and you are confident with passing data safely between threads. Otherwise, go for the non-blocking IO route.

share|improve this answer
    
A client not sending data will only block that client's thread, not in any way cause the server to run improperly. He is already using threads. –  Ricket Apr 25 '11 at 17:37
    
So, someone can log in lots of clients and leave them all dormant, eating up memory. You must never leave your system at the mercy of clients because that's how denial of service attacks happen. –  Kylotan Apr 25 '11 at 18:58
    
Would that not be the case for any server? –  Ricket Apr 26 '11 at 3:57
1  
Depends what kind of server it is, but the general theme is that the content of the server's response may depend on the client but the actual response must not - if the client doesn't submit the request in time, or submits an invalid request, the connection is dropped. Servers have to assume clients are malicious and malformed and not base their own control flow around the client. –  Kylotan Apr 26 '11 at 22:10
add comment

Java's NIO package (as of Java6), provides support for non-blocking I/O only, via Selectors.

share|improve this answer
    
Is that the best option though? What is the advantage of this over sending dummy packets to the server? –  Tim Cooper Apr 24 '11 at 16:12
    
Yes, NIO is the best option for a server handling many clients. One thread per client has a huge overhead for context switching. And as a solution to your current code, dummy packets would be very wasteful (a lot more incoming bandwidth that the server has to handle) and inconsistent. Each client's connection would then run at different rates depending on the client's connection speed and quality. Terrible idea. The read call should not block, whether you use the old non-blocking ways or restructure your server for NIO. –  Ricket Apr 25 '11 at 17:40
    
@user6924 just to clarify the NIO was introduced in Java1.4 you can check it even in wiki –  Boro May 8 '11 at 8:56
add comment

I agree with the other answers that NIO provides better results. However using NIO isn't that trivial. You will definitely learn something when you code the NIO network code yourself. Or you just use an asynch network package like netty or Apache Mina. I prefer netty, since I find it better documented. However if you understand one of them, you understand the other one as well.

But, if you want to keep the design you have, you can split the sending and receiving code. Create some "PlayerSession" or "PlayerConnection" Object that provides the methods for sending messages to the client and contains one thread that blocks on the read and handles input. Maybe you want to move the sending stuff to an own thread, just try it.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.