The {@code backlog} parameter is the 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. If the {@code backlog} parameter has the value {@code 0}, or a negative value, then an implementation specific default is used.
// ServerSocketChannelImpl#bind public ServerSocketChannel bind(SocketAddress local, int backlog)throws IOException { synchronized (lock) { if (!isOpen()) thrownew ClosedChannelException(); if (isBound()) thrownew AlreadyBoundException(); InetSocketAddress isa = (local == null) ? new InetSocketAddress(0) : Net.checkAddress(local); SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkListen(isa.getPort()); NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort()); // 将socket绑定到本地地址和端口 Net.bind(fd, isa.getAddress(), isa.getPort()); // 监听连接请求,并设置backlog的值 Net.listen(fd, backlog < 1 ? 50 : backlog); synchronized (stateLock) { localAddress = Net.localAddress(fd); } } returnthis; }
从中可以看到,如果 backlog 的值设置为 0 或负数,那么将会使用默认值 50
Net.listen 底层使用的是 listen 系统调用,可通过 man 2 listen 查看 listen 的说明
1 2 3 4 5 6 7
Creation of socket-based connections requires several operations. First, a socket is created with socket(2). Next, a willingness to accept incoming connections and a queue limit for incoming connections are specified with listen(). Finally, the connections are accepted with accept(2). The listen() call applies only to sockets of type SOCK_STREAM.
The backlog parameter defines the maximum length for the queue of pending connections. If a connection request arrives with the queue full, the client may receive an error with an indication of ECONNREFUSED. Alternatively, if the underlying protocol supports retransmission, the request may be ignored so that retries may succeed.
accept() extracts the first connection request on the queue of pending connections, creates a new socket with the same properties of socket, and allocates a new file descriptor for the socket. If no pending connections are present on the queue, and the socket is not marked as non-blocking, accept() blocks the caller until a connection is present. If the socket is marked non-blocking and no pending connections are present on the queue, accept() returns an error as described below.
// Determine the default somaxconn (server socket backlog) value of the platform. // The known defaults: // - Windows NT Server 4.0+: 200 // - Linux and Mac OS X: 128 int somaxconn = PlatformDependent.isWindows() ? 200 : 128; File file = new File("/proc/sys/net/core/somaxconn"); BufferedReader in = null; try { // file.exists() may throw a SecurityException if a SecurityManager is used, so execute it in the // try / catch block. // See https://github.com/netty/netty/issues/4936 if (file.exists()) { in = new BufferedReader(new FileReader(file)); somaxconn = Integer.parseInt(in.readLine()); if (logger.isDebugEnabled()) { logger.debug("{}: {}", file, somaxconn); } } else { // Try to get from sysctl Integer tmp = null; if (SystemPropertyUtil.getBoolean("io.netty.net.somaxconn.trySysctl", false)) { tmp = sysctlGetInt("kern.ipc.somaxconn"); if (tmp == null) { tmp = sysctlGetInt("kern.ipc.soacceptqueue"); if (tmp != null) { somaxconn = tmp; } } else { somaxconn = tmp; } }
if (tmp == null) { logger.debug("Failed to get SOMAXCONN from sysctl and file {}. Default: {}", file, somaxconn); } } } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Failed to get SOMAXCONN from sysctl and file {}. Default: {}", file, somaxconn, e); } } finally { if (in != null) { try { in.close(); } catch (Exception e) { // Ignored. } } } return somaxconn;