Troels
Troels

Reputation: 231

Client seems to be connected without the server accepting it

I was trying to illustrate a problem with a socket server and client, where the server was supposed to handle only one client at a time, and so multiple clients would have to wait for each other.

This is my server class. I can accept a connection from one client, read some string, upper case it and send it back. Then the next client would be served. So if I start multiple clients, the first would connect, but the rest would have to wait for the server to call accept() again. That was the assumption.

System.out.println("Starting server...");

try {
    ServerSocket welcomeSocket = new ServerSocket(2910);

    while(true) {
        Socket socket = welcomeSocket.accept();
        System.out.println("client connected");

        ObjectInputStream inFromClient = new ObjectInputStream(socket.getInputStream());
        String o = (String)inFromClient.readObject();
        System.out.println("Received: " + o);

        String answer = o.toUpperCase();

        ObjectOutputStream outToClient = new ObjectOutputStream(socket.getOutputStream());
        System.out.println("Sending back: " + answer);
        outToClient.writeObject(answer);
    }
} catch (IOException | ClassNotFoundException e) {
    // socket stuff went wrong
}

Here's my client code:

try {
    Socket socket = new Socket("localhost", 2910);
    System.out.println("Connected to server");
    ObjectOutputStream outToServer = new ObjectOutputStream(socket.getOutputStream());
    Scanner in = new Scanner(System.in);
    System.out.println("What to send?");
    String toSend = in.nextLine();
    System.out.println("Sending " + toSend);
    outToServer.writeObject(toSend);

    ObjectInputStream inFromServer = new ObjectInputStream(socket.getInputStream());
    String o = (String)inFromServer.readObject();

    System.out.println("Received: " + o);
} catch (IOException | ClassNotFoundException e) {}

I create the connection to the server, and then read from the console. The first client should connect successfully, and then print out "connected to server". The other clients should get stuck on creating the Socket, until the server calls accept(). Or so I thought.

But all my clients print out "Connected to server", and I can type into the console for all clients, and this is sent to the server. The server will then still respond to one client at a time.

But why does my client code move on from the initial connection before my server accepts the connection? This seemed to be the case in java 8, but now I'm using java 11.

Upvotes: 1

Views: 449

Answers (1)

Set the backlog to 1 if you want to prevent the operating system from accepting multiple connections until you call accept().

Otherwise, the OS will accept up to typically 5 connections before you call accept(). The clients believe to be connected because they are, indeed, connected at a TCP/IP level.


See the documentation:

public ServerSocket(int port, int backlog) throws IOException Creates a server socket and binds it to the specified local port number, with the specified backlog. A port number of 0 means that the port number is automatically allocated, typically from an ephemeral port range. This port number can then be retrieved by calling getLocalPort. The maximum queue length for incoming connection indications (a request to connect) is set to the backlog parameter. If a connection indication arrives when the queue is full, the connection is refused.

If the application has specified a server socket factory, that factory's createSocketImpl method is called to create the actual socket implementation. Otherwise a "plain" socket is created.

If there is a security manager, its checkListen method is called with the port argument as its argument to ensure the operation is allowed. This could result in a SecurityException. The backlog argument is the requested maximum number of pending connections on the socket. Its exact semantics are implementation specific. In particular, an implementation may impose a maximum length or may choose to ignore the parameter altogther. The value provided should be greater than 0. If it is less than or equal to 0, then an implementation specific default will be used.

Parameters: port - the port number, or 0 to use a port number that is automatically allocated. backlog - requested maximum length of the queue of incoming connections.

Upvotes: 2

Related Questions