How can I handle multiple clients connected to a server using sockets?

Chucky picture Chucky · Mar 4, 2013 · Viewed 21k times · Source

I have an Android app that needs to let multiple devices connect. One device should act as the group owner and issue instructions to all of the clients to do specific things. I suppose it's comparable to a wireless handheld game where one player is the host.

I have a couple of questions so I will try to keep them concise. Even an answer to just the first would help.

First, I've successfully paired a single server and single client phone using sockets. I did this using Android's Wi-Fi Direct technology (Described here). The tutorial is helpful but unfortunately not very thorough, particularly in describing one-to-many connections. Once a peer list is found, socket connections can be opened. I was able to connect two devices using a thread for the server (Using this example), like so:

public class ServerThread implements Runnable {

        public void run() {
             (Code...)
             client = serverSocket.accept();
             (...other code here.)
        }
}

A client is created following a button press (I think, still trying to get my head around my modified code):

public class MusicClientThread implements Runnable {
     Socket socket = new Socket(serverAddr, port);
     while (connected) {
          //(Other code here.)
          while ((line = in.readLine()) != null) {
          //While there are still messages coming
          }
     }
     socket.close();
     //(Other code here too.)
}

So I suppose my first question is: How would I allow more clients to be connected? My ServerThread refers to a single client variable above so I do not see how I would allow a varying number (my application is aiming for anything from 2 to 10 users) nor do I know the correct way to differentiate between all my different clients. My only guess is that I would use the unique IP address of each phone.

My 2nd question is, once I've established a connection with multiple clients/peers, how would I then send and receive instructions to them correctly? Currently my single server awaits an instruction, and upon receiving it, issues a response instruction. I need it so that the server can send instructions from the start, using button presses, and the result of these is visible on the client devices.

I hope I have made everything clear!

Answer

ddmps picture ddmps · Mar 4, 2013

You have to start a new thread for each client, as the sockets need a thread for themselves to run (as it waits for input most of the time). This can for example be done (in this simplified manner):

public class ThreadHandler extends Thread {
      private ArrayList<ServerThread> serverThreads = new ArrayList<ServerThread>();
      public void run() {
            while (!isInterrupted()) { //You should handle interrupts in some way, so that the thread won't keep on forever if you exit the app.
                  (Code...)
                  ServerThread thread = new ServerThread(serverSocket.accept());
                  serverThreads.add(thread);
                  thread.start();
            }
      }
      public void doSomethingOnAllThreads() {
            for (ServerThread serverThread : serverThreads) {
                  serverThread.otherMethod();
            }
      }
}

Where the ServerThread looks something like this:

public class ServerThread extends Thread {
    private Socket socket;
    public ServerThread(Socket socket) {
          this.socket = socket;
    }
    public void run() {
         (...other code here.)
    }
    public void otherMethod() {
          //Signal to the thread that it needs to do something (which should then be handled in the run method)
    }
}