我正在运行以下代码,它只是在无限循环中连接和关闭套接字:

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;

public class Main {
    public static void main(String[] args) throws Exception {
        Thread.sleep(1000);
        InetAddress localhost = InetAddress.getByName("127.0.0.1");
        InetSocketAddress localhostRpcbind = new InetSocketAddress(localhost, 111);
        SelectorProvider selectorProvider = SelectorProvider.provider();
        long iterations = 0;
        while (true) {
            try {
                SocketChannel socketChannel = selectorProvider.openSocketChannel();
                socketChannel.connect(localhostRpcbind);
                socketChannel.finishConnect();
                socketChannel.close();
                iterations ++;
            } catch (Exception e) {
                System.err.println("after " + iterations + " iterations");
                e.printStackTrace(System.err);
                throw e;
            }
        }
    }
}

端口111是rpcbind的端口(已在我的计算机上运行)。
在代码的第一轮运行中,我会得到类似的信息:
after 28239 iterations
java.net.BindException: Cannot assign requested address
    at sun.nio.ch.Net.connect0(Native Method)
    at sun.nio.ch.Net.connect(Net.java:458)
    at sun.nio.ch.Net.connect(Net.java:450)
    at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:648)
    at Main.main(Main.java:16)

随后的运行将立即失败(0次迭代),直到一段时间后我再次获得第一个结果(大约26-28k次迭代然后失败)。

怎么回事,如何使此连接/断开循环无限期正确运行?

我在Linux x64(fedora 22)上运行。

注意:是的,我知道代码没有用,什么也不做,这是我要研究的更大问题的SSCCE。

更新-看起来我在我的计算机上遇到了短暂的端口耗尽:
$ cat /proc/sys/net/ipv4/ip_local_port_range
32768   61000

所以我有〜28k个临时端口用于连接,这与我的错误相符

最佳答案

在绑定(bind)到大约28K个不同的端口后,系统用完了临时端口来绑定(bind)您的套接字。

出现此问题的原因是,为了打开TCP连接,操作系统分配了一个临时端口(用于源端口)。它将套接字绑定(bind)到分配的端口。关闭TCP连接后,由于历史原因(https://en.wikipedia.org/wiki/File:Tcp_state_diagram_fixed_new.svg),该连接通常处于TIME_WAIT状态,持续2分钟,从我的 Angular 来看,在当今大多数系统中,该时间可以缩短。 。

作为一种解决方案,您可以使用sysctl减少此超时:

将net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait的值更改为一个较小的数字(如1),情况将会改善。但是,如果您的应用程序足够快,可以在不到1秒的时间内消耗约28,000个端口,那么您仍然会看到此异常。

您可以调整的其他TCP参数:
增加临时端口的范围:net.ipv4.ip_local_port_range
net.ipv4.tcp_tw_reuse
net.ipv4.tcp_tw_recycle

查看:http://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux.htmlhttp://www.lognormal.com/blog/2012/09/27/linux-tcpip-tuning/

关于java - java.net.BindException : Cannot assign requested address when opening too many connections,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31876441/

10-12 19:38