13

I was running a few tests with sockets, and I encountered some strange behavior: A ServerSocket will refuse connections after the 50th client Socket connects to it, even if that client socket is closed before the next one is opened, and even if a delay is added between connections.

The following program is my experimental code, which in its current state, throws no exceptions and terminates normally. However, if the array size of Socket[] clients is increased beyond 50, any client sockets attempting to connect after the 50th connection are refused by the server socket.

Question: Why is 50 the count at which socket connections are refused by a server socket?

public static void main(String[] args) {
    try (ServerSocket server = new ServerSocket(2123)) {
        Socket[] clients = new Socket[50];
        for (int i = 0; i < clients.length; i++) {
            clients[i] = new Socket("localhost", 2123);
            System.out.printf("Client %2d: " + clients[i] + "%n", i);
            clients[i].close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

I have run tests where another 50 sockets connect to another local server, and no issue occurred with 100 sockets being opened and closed, so I've deduced that its the server socket is refusing connections, and not some limit of opening client sockets, but I have been unable to discover why the server socket is limited to 50 connections, even though they are not connected simultaneously.

FThompson
  • 27,043
  • 11
  • 53
  • 89

4 Answers4

16

It's all in the JavaDoc:

The maximum queue length for incoming connection indications (a request to connect) is set to 50. If a connection indication arrives when the queue is full, the connection is refused.

Apparently your ServerSocket never accepts any connections, just listens. You must either call accept() and start handling the connection or increase the backlog queue size:

new ServerSocket(port, 100)
Tomasz Nurkiewicz
  • 311,858
  • 65
  • 665
  • 652
  • 2
    Wouldn't the connections in the queue be removed when the client sockets are closed? – FThompson Oct 19 '12 at 20:32
  • 1
    @EJP Yeah, but why would they not? To me, it seems odd that closed sockets remain queued for connection. I guess that there's no way for the server socket to know that the client socket closed though. – FThompson Oct 19 '12 at 21:31
  • 5
    @Vulcan just when accept() method is called, the connection is removed from the queue. Sorry for the 3 years late comment – Alan Deep Apr 25 '15 at 00:27
4

50 is the default value for backlog

http://docs.oracle.com/javase/1.4.2/docs/api/java/net/ServerSocket.html#ServerSocket%28int%29

The maximum queue length for incoming connection indications (a request to connect) is set to 50. If a connection indication arrives when the queue is full, the connection is refused.

irreputable
  • 42,827
  • 9
  • 59
  • 89
2

Here's an example that works, in accordance with @TomaszNurkiewicz's answer:

import java.net.*;
import java.util.concurrent.atomic.AtomicBoolean;

public class SockTest{
public static void main(String[] args) {
    final AtomicBoolean shouldRun = new AtomicBoolean(true);
    try  {
        final ServerSocket server = new ServerSocket(2123);
        Thread serverThread = new Thread(){
           public void run() {
              try {
                 while(shouldRun.get()) {
                 Socket s = server.accept();
                 s.close();
             Thread.sleep(1);
                }
              } catch(Exception ex) {
                ex.printStackTrace();
              }
           }
        };
        serverThread.start();
        Socket[] clients = new Socket[150];
        for (int i = 0; i < clients.length; i++) {
            clients[i] = new Socket("localhost", 2123);
            System.out.printf("Client %2d: " + clients[i] + "%n", i);
            clients[i].close();
        }
        shouldRun.set(false);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
       shouldRun.set(false);
    }

  }
}
GreyBeardedGeek
  • 26,236
  • 2
  • 39
  • 58
  • Thanks; I actually created a similar example after seeing @TomaszNurkiewicz's answer earlier, but not as cleanly done as yours (I forgot about AtomicBoolean and made my own makeshift class with the same functionality haha). +1 – FThompson Oct 19 '12 at 21:34
0

Two things you may look at

  1. Server is not accepting connection.
  2. Server is unable to cater too many connection at same time instance. It might caused by increased backlog (beyond 50). Try giving some time gap in milli seconds before connecting to server again. Like ramp up connections. I solved it by giving some time gap when i ran test load.