我运行以下代码,它只是在无限循环中连接和关闭套接字:
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;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
端口 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)
Run Code Online (Sandbox Code Playgroud)
后续运行将立即失败(0次迭代),直到一段时间后我再次得到第一个结果(〜26-28k迭代然后失败)。
发生了什么事,我怎样才能让这个连接/断开循环无限期地正确运行?
我在 Linux x64 (fedora 22) 上运行。
注意:是的,我知道代码是无用的并且什么也不做,这是我正在尝试调查的一个更大问题的 SSCCE。
更新- 看起来我的机器上遇到了短暂的端口耗尽:
$ cat /proc/sys/net/ipv4/ip_local_port_range
32768 61000
Run Code Online (Sandbox Code Playgroud)
所以我有 ~28k 临时端口用于连接,这与我的错误相符
在绑定到大约 28K 不同的端口后,系统已经用完了用于绑定套接字的临时端口。
此问题的原因是,为了打开 TCP 连接,操作系统会分配一个临时端口(用于源端口)。它将套接字绑定到分配的端口。TCP 连接关闭后,由于历史原因(https://en.wikipedia.org/wiki/File:Tcp_state_diagram_fixed_new.svg),连接会处于 TIME_WAIT 状态,通常持续 2 分钟,从我的角度来看,这是在当今的大多数系统中,时间都可以减少...其他讨论的主题。
作为一种解决方案,您可以使用 sysctl 减少此超时:
将 net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait 的值更改为较低的数字(例如 1),情况将会改善。然而,如果您的应用程序足够快,可以在不到 1 秒的时间内消耗约 28K 端口,您仍然会看到此异常。
您可以调整的其他 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.html,http : //www.lognormal.com/blog/2012/09/27/linux -tcpip-调整/
| 归档时间: |
|
| 查看次数: |
5235 次 |
| 最近记录: |