how does a multi-threaded server work?

2019-08-27 18:53发布

问题:

I've got from someone this example with a multithreaded server on android:

http://tutorials.jenkov.com/java-multithreaded-servers/singlethreaded-server.html

But I have a few difficulties in understanding a part of the code:

while(! isStopped()) {
    Socket clientSocket = null;
    try {
        clientSocket = this.serverSocket.accept();
    } catch (IOException e) {
        if (isStopped()) {
            System.out.println("Server Stopped.") ;
            return;
        }
        throw new RuntimeException("Error accepting client connection", e);
    }

What I don't understand is, what happens when I have an exception at this line:

clientSocket = this.serverSocket.accept();

From what I can tell is that this function gets called:

private synchronized boolean isStopped() {
    return this.isStopped;
}

But how it gets to close that socket? Cause if u get exception in the attempt to accept a client you should close the socket returned by accept.

I assume that this is done in here:

public synchronized void stop() {
    this.isStopped = true;
    try {
        this.serverSocket.close();
    } catch (IOException e) {
        throw new RuntimeException("Error closing server", e);
    }
}

But where is stop() called,how it gets to make the connection between isStopped() and onStop()....And what is with that "synchronized"?

Hope I've been clear with my unclarities! Thank u in advance:)

回答1:

You've probably moved on but for posterity...

what happens when I have an exception at this line

clientSocket = this.serverSocket.accept();

If you get an exception inside of accept then no socket is returned so there is nothing to close. Either accept() returns a valid socket that you should handle and then close or it throws an exception. Never both.

where is stop() called?

Stop looks to be called from the outside world by some caller that wants to shutdown the server socket. With a server, you create a server-socket and then you accept individual connections to remote clients, which returns a socket for that client. Each of the client handlers need to close their own individual connections. When the server is shutting down (in this case when stop() is called), the server-socket is then closed.

Once stop() is called then the server socket is closed and the accept() method will throw an exception. That's why there is a if(isStopped()) check in the code to avoid throwing an exception.

how it gets to make the connection between isStopped() and onStop()

isStopped() is a private method that tests to see if someone has called the stop() method. I assume onStop() is an Android method? They are not related although someone might want to call singleThreadedServer.stop() inside of onStop().

what is with that synchronized?

The synchronized keyword is used by multithreaded programs as a mutex and memory barrier. It only allows 1 thread to be executing inside of the synchronized block at one time. It also makes sure that all of the local variables are synced between the threads and central memory. See the java docs:

http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

Having that private method be synchronized is really gross IMO. I assume this is being done to make sure isStopped has been updated. I would have used a volatile boolean or AtomicBoolean instead.