1

Right now I am playing a little arround with Client-Server application for example to communicate via a java application with a raspberry pi which runs a server application.

Well by this I found a problem and I dont find a possible solution. Using the following code I can connect twice to server but after 2 connects it will not accept any more connections. For example I start the Client the first time, and it works everything nicely. Then I close the client and start it again and it works again. But if I close it and start it a 3rd time, it will do nothing. The server will not accept the connection. I tried it with different pcs in my private network but never got a 3rd connection running.

Here is the Code I am running on the server:

public class Receiver {

private final Logger logger = Logger.getLogger(this.getClass().getName());

private ServerSocket serverSocket;
private boolean isRunning;

public Receiver(int port) {
    isRunning = true;
    try {
        serverSocket = new ServerSocket(port);
        logger.log(Level.FINER, "start listening at port " + port);
        logger.log(Level.FINER, "established successful.");
    } catch (IOException e) {
        logger.log(Level.SEVERE, "Error while opening socket:\n" + LogUtil.getStackTrace(e));
        System.exit(1);
    }
}

/**
 * server starts to listen at the specific port
 */
public void listenServer() {
    logger.log(Level.FINER, "Server is listening");

    while (isRunning) {
        try {
            final Socket clientsocket = serverSocket.accept();
            logger.log(Level.FINER, "Server accepted Connection from " + clientsocket.getInetAddress());
            new Thread(new Runnable() {

                @Override
                public void run() {
                    handleConnection(clientsocket);
                }
            }).start();
        } catch (IOException e) {
            logger.log(Level.SEVERE, "Connection with Client failed.");
        }
    }
}

/**
 * handles the given connection
 * 
 * @param clientSocket
 *            the given client socket for this connection
 */
private void handleConnection(Socket clientSocket) {

    ObjectInputStream instream = null;
    ObjectOutputStream outstream = null;

    try {
        outstream = new ObjectOutputStream(clientSocket.getOutputStream());
        instream = new ObjectInputStream(clientSocket.getInputStream());
        final RequestProcessor processor = new RequestProcessor();
        final InetAddress inetAdress = clientSocket.getInetAddress();

        logger.log(Level.FINER, "handle connection from " + inetAdress);

        Object inob;
        while ((inob = instream.readObject()) != null) {
            logger.log(Level.FINER, "received Object from " + inetAdress);
            final ObjectOutputStream finalOutputStream = outstream;
            final Object finalInob = inob;

            new Thread() {
                public void run() {
                    setPriority(MAX_PRIORITY);
                    Object outob;
                    try {
                        outob = processor.processObject(finalInob);
                        logger.log(Level.FINER, "send Respond to: " + inetAdress + " Error: " + (outob instanceof ErrorMessage));
                        finalOutputStream.writeObject(outob);
                        finalOutputStream.flush();
                    } catch (IOException e) {
                        logger.log(Level.SEVERE, "Connection closed to " + inetAdress);
                    }
                }
            }.start();
        }

        closeConnection(clientSocket, instream, outstream);
    } catch (IOException e) {
        logger.log(Level.SEVERE, "Connection closed to " + clientSocket.getInetAddress());
    } catch (ClassNotFoundException e) {
        logger.log(Level.SEVERE, "Connection closed to " + clientSocket.getInetAddress());
    } finally {
        closeConnection(clientSocket, instream, outstream);
    }

}

/**
 * closes InputStream, OutputStream and socket
 * 
 * @param socket
 * @param instream
 * @param outstream
 */
private void closeConnection(Socket socket, InputStream instream, OutputStream outstream) {
    this.isRunning = false;
    if (instream != null) {
        try {
            instream.close();
        } catch (IOException e) {
        }
    }
    if (outstream != null) {
        try {
            outstream.close();
        } catch (IOException e) {
        }
    }
    if (socket != null) {
        try {
            socket.close();
        } catch (IOException e) {
        }
    }
    logger.log(Level.FINER, "Connection was closed to client " + socket.getInetAddress());
}

/**
 * closes all connections and ends the server
 */
public void endAllConnections() {
    this.isRunning = false;

    if (this.serverSocket != null)
        try {
            this.serverSocket.close();
        } catch (IOException e) {
            // do nothing
        }
      }
  }

and here is the client code which I am using to connect to this server:

public class SocketConnector implements IConnector {

    private final Logger logger = Logger.getLogger(this.getClass().getName());

    private Socket s;
    private ObjectOutputStream oos;
    private ObjectInputStream ois;

    /**
     * creates a new connection
     * 
     * @param host
     *            given host
     * @param port
     *            given port
     * 
     * @throws UnknownHostException
     * @throws IOException
     */
    public SocketConnector(String host, int port) throws UnknownHostException, IOException {
        logger.log(Level.FINER, "Establish connection to " + host + ":" + port);
        s = new Socket(host, port);
        oos = new ObjectOutputStream(s.getOutputStream());
        ois = new ObjectInputStream(s.getInputStream());
    }

        // some methos which use oos and ois.

Does someone maybe know why the server does not accept any more connections when 2 clients connected and disconnected from it? I googled alot arround but didn't find an adequate answer :/ The server log says it doesn't even accept the new connection.

Thanks in advance :)

4
  • Are your running in in Windows? Because I think there is a TCP/IP stack limit of 2 connection per host, which you can adjust by messing with the Windows Registry (or using alternate host names like IP address and host names) Commented Jan 15, 2014 at 19:36
  • There are other problems with this code. 1. The object streams should be created in the run() method, not the constructor: otherwise they execute in the accept() thread, potentially blocking it. 2. ObjectInputStream doesn't return null unless you wrote a null, so looping while it doesn't return a null doesn't make sense. It throws EOFException at end of stream: catch that, and break when you get it. @JasonSperske There is a TCP backlog limit but it is considerably higher than 2. Commented Jan 15, 2014 at 20:26
  • Thank you. Vutran solved the major problem. I will take a look on it again to follow your advices to make it cleaner EJP :) Commented Jan 15, 2014 at 20:33
  • There's another problem. The Runnable you start for each incoming connection should have nothing to do with the server class and shouldn't invoke methods in it. This is really the basic problem. Commented Jan 15, 2014 at 22:33

1 Answer 1

2

The situation is:
when calling final Socket clientsocket = serverSocket.accept(); the first time, it's waiting for the first client. when the first client connected, you pass this client to a thread then continue the loop that calls final Socket clientsocket = serverSocket.accept(); the second time. Since starting a thread take more time than going to the next loop, isRunning still is true. In handleConnection(Socket clientSocket), you call closeConnection(clientSocket, instream, outstream); which set isRunning to false. That is the point. When the second client connected, you also pass this client to another thread, then continue the loop where isRunning is false, so the loop is terminated. Hence, you can't get to the third client.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you :) that was the problem. Shame I didn't see that :/ Really didn't see I set it to false ^^

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.