-1

I've been into game-developing for a while, and I'm trying to make my next game multi-player. I'm trying to write a server that will loop through every 1/16th of a second or so to calculate the position of all the entities and such in the game. The client will then be able to request all this information when it needs to.

As such, I tried writing a simple server/client that can exchange information. Part of the code can be seen here:

ServerSocket listener;
Socket socket;

while(running)
{
    socket = listener.accept();

    PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
    out.println("information"); //sending the string "information" to any client that has connected
}

The only issue is that the server waits for the client to connect every time listener.accept() is called, therefore halting everything else in the loop that would need to be done. How can I make it so that many clients can connect/request information without the server stopping to specifically listen for them every single time? I really don't have much of a clue when it comes to all this networking stuff, which is why I'm trying to learn. I've never delved into it, so I apologize if it's a seemingly simple solution.

(hopefully I have the right idea on how games work here? I'd think position and everything is server-side, and the only things handled client-side are rendering and user-input and such.)

TheNewGuy
  • 411
  • 1
  • 7
  • 13
  • 1
    You might consider using something like Netty for client/server programming, this is a well established and widely used library for network communication. They have excellent examples (check out the simple Echo example for the basics) http://netty.io/wiki/ – Alex Jan 04 '15 at 20:37
  • Take a look at the Custom Networking section of the Java Tutorial. – user207421 Jan 04 '15 at 22:45

2 Answers2

3

If it is a simple solution, you should consider simply mutli-threading the handling of the requests, so each listener runs separately from the main program code: http://tutorials.jenkov.com/java-multithreaded-servers/multithreaded-server.html

Also, if the game involves precise movements, e.g. shooting, you should consider a slightly faster tickrate.

Rodolffo
  • 105
  • 1
  • 6
  • Basically, you don't listen to incoming connections inside the while block in Main(), as until each request arrives, the program is stuck within the while block. What you need to do is create a new class, which implements the Runnable interface: (adding code in the new comment) – Rodolffo Jan 04 '15 at 20:50
  • public class MultiThreadedServer implements Runnable{ and copy the whole code after that, then you can run it with MultiThreadedServer server = new MultiThreadedServer(9000); new Thread(server).start(); @rozkosz – Rodolffo Jan 04 '15 at 20:52
  • Upvoted, but don't post code in comments. It's completely illegible. Edit it into your answer. – user207421 Jan 04 '15 at 22:46
1

You need to switch to NIO, which gives non-blocking capabilities:

class Server {
    public static void main(String[] args) {
        try {
            ServerSocketChannel serverSocket = ServerSocketChannel.open();
            serverSocket.configureBlocking(false);
            serverSocket.bind(port);

            while(running) {
                SocketChannel channel = serverSocket.accept();

                //...
            }
        }
    }
}

When serverSocket.accept() is called, it'll return null if there is no connection to accept, instead of blocking.

You could also use a Selector to manage reading/writing and accepting on a single thread. Keep in mind, you'd need a thread for each user as well to block for reading. Instead, a Selector will notify you of when you need to read from any channel.

Am_I_Helpful
  • 18,735
  • 7
  • 49
  • 73
Vince
  • 14,470
  • 7
  • 39
  • 84
  • 2
    Non-blocking NIO is a pretty advanced topic for some one not familiar with using more than one thread. – Peter Lawrey Jan 04 '15 at 21:01
  • @PeterLawrey That's somewhat contradicting; this prevents the need to create new threads. As long as he looks into how to use a `ByteBuffer`, I think he'll be alright. I understand some topics might be a bit rough, but its easier than needing to dig into synchronization and atomicy – Vince Jan 04 '15 at 21:06
  • 2
    how many java developers do you know when to use flip vs compact ;) – Peter Lawrey Jan 04 '15 at 21:07
  • @PeterLawrey You'd use flip to prepare the buffer for reading (resets position, sets limit to position's previous position to mark how many bytes can be read into the buffer), then once you're ready to write, you'd use compact to ensure any data you didn't read from the buffer doesn't get overriden. Is that correct? If so, all of my programming buddies that use NIO understand. I admit it's a lot more low-level, but I believe it would be the right path to take – Vince Jan 04 '15 at 21:21
  • that is reasonable. I find most developers have trouble grasping such low level considerations. – Peter Lawrey Jan 04 '15 at 21:25
  • You could pass in the StringBuilder to be appended to. This way you only need one. – Peter Lawrey Jan 04 '15 at 21:28
  • You've just proved @PeterLawrey's point. You use `flip()` to prepare a buffer for `write()` or `get()`. Not for reading. There is nothing in this question that *requires* the OP to use NIO. It's only one of three options. – user207421 Jan 04 '15 at 22:44
  • @EJP It's definitely the right way to go, though. He's making a multiplayer game, in which many clients will be connecting to a server. Using a thread-per-client system will require the server to spawn hundreds of threads just to manage it's users. If you ask me, telling him to spawn new threads for each client as well as a thread to listen for connections (not to mention his gameloop thread..) isn't a good recommendation and sets him on the wrong path. There is no reason to downvote this either, as it is definitely a solution.. – Vince Jan 04 '15 at 22:50
  • @EJP (continued) and downvoting this would be similar to downvoting someone who gives an answer on using (gui) Layout Managers instead of absolute positioning (which will help the user achieve what he wants), rather than just putting a bandaid on the code smell. How will people improve if they don't get shown the correct way, and build on top of foundations not suitable for their situation? And saying I proved his point is saying he proved his own point.. – Vince Jan 04 '15 at 22:52
  • @EJP And just a final heads up, `get()` reads from the buffer. So please, explain the downvote? – Vince Jan 04 '15 at 23:13