SocketServer 总是为动态端口抛出 BindException
SocketServer Always Throws BindException for Dynamic Ports
Definitions
Well-known Port
Port number in the range [0, 1023]
Registered Port
Port number in the range [1024, 49151]
Dynamic Port
Port number in the range [49152, 65535]
我正在尝试创建一个 SocketServer
对象。当我允许 SocketServer
到 select 一个动态端口(通过绑定到端口 0)时,它按预期工作。如果我明确指定注册端口,它会按预期工作。但是,当我指定一个动态端口时,它总是抛出一个 BindException
并显示消息“ 地址已在使用:JVM_Bind”。异常堆栈跟踪的顶部是:
at java.net.DualStackPlainSocketImpl.bind0(Native Method)
at java.net.DualStackPlainSocketImpl.socketBind(DualStackPlainSocketImpl.java:106)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:387)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:190)
at java.net.ServerSocket.bind(ServerSocket.java:375)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:128)
我在 Windows 7 Enterprise SP1 x64 机器上使用 JDK 1.8u74。代码如下:
SocketServer createServer(final int port) throws IOException {
// Create a new socket server
SocketServer server;
try {
// Try to bind to all interfaces
server = new ServerSocket(port, 1, null);
} catch (BindException e) {
// If that fails, try to bind to the primary IP address
final InetAddress address = InetAddress.getLocalHost();
server = new ServerSocket(port, 1, address);
}
return server;
}
我还尝试了以下替代方法:
SocketServer createServer(final int port) throws IOException {
// Create a new socket server
final SocketServer server = new SocketServer();
server.setReuseAddress(true);
try {
// Try to bind to all interfaces
server.bind(new InetSocketAddress(port), 1);
} catch (BindException e) {
// If that fails, try to bind to the primary IP address
final InetAddress address = InetAddress.getLocalHost();
server.bind(new InetSocketAddress(address, port), 1);
}
return server;
}
当 port
是动态端口时,这两种选择都会抛出 BindException。根据netstat -an
的结果,我已经验证了我测试的大约50个动态端口都是可用的。有没有办法为特定的动态端口创建 SocketServer
?
虽然不理想,因为它涉及注册表编辑,但在 Server Fault 上提供了答案。
Windows 可以设置为从其动态端口范围中排除端口。只需将要排除的范围添加到多字符串值:
HKLM\System\CurrentControlSet\Services\TCPIP\Parameters\ReservedPorts
因此,就我而言,我需要使用端口 55101-55107,因此我将该文本添加到注册表值并重新启动了计算机。虽然此解决方案允许我使用这些端口,但令人失望的是我必须在我想使用它们的任何 Windows 机器上编辑注册表。另外,如果我以后要添加另一个动态端口,我将不得不重新编辑注册表。
Definitions
Well-known Port
Port number in the range [0, 1023]
Registered Port
Port number in the range [1024, 49151]
Dynamic Port
Port number in the range [49152, 65535]
我正在尝试创建一个 SocketServer
对象。当我允许 SocketServer
到 select 一个动态端口(通过绑定到端口 0)时,它按预期工作。如果我明确指定注册端口,它会按预期工作。但是,当我指定一个动态端口时,它总是抛出一个 BindException
并显示消息“ 地址已在使用:JVM_Bind”。异常堆栈跟踪的顶部是:
at java.net.DualStackPlainSocketImpl.bind0(Native Method)
at java.net.DualStackPlainSocketImpl.socketBind(DualStackPlainSocketImpl.java:106)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:387)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:190)
at java.net.ServerSocket.bind(ServerSocket.java:375)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:128)
我在 Windows 7 Enterprise SP1 x64 机器上使用 JDK 1.8u74。代码如下:
SocketServer createServer(final int port) throws IOException {
// Create a new socket server
SocketServer server;
try {
// Try to bind to all interfaces
server = new ServerSocket(port, 1, null);
} catch (BindException e) {
// If that fails, try to bind to the primary IP address
final InetAddress address = InetAddress.getLocalHost();
server = new ServerSocket(port, 1, address);
}
return server;
}
我还尝试了以下替代方法:
SocketServer createServer(final int port) throws IOException {
// Create a new socket server
final SocketServer server = new SocketServer();
server.setReuseAddress(true);
try {
// Try to bind to all interfaces
server.bind(new InetSocketAddress(port), 1);
} catch (BindException e) {
// If that fails, try to bind to the primary IP address
final InetAddress address = InetAddress.getLocalHost();
server.bind(new InetSocketAddress(address, port), 1);
}
return server;
}
当 port
是动态端口时,这两种选择都会抛出 BindException。根据netstat -an
的结果,我已经验证了我测试的大约50个动态端口都是可用的。有没有办法为特定的动态端口创建 SocketServer
?
虽然不理想,因为它涉及注册表编辑,但在 Server Fault 上提供了答案。
Windows 可以设置为从其动态端口范围中排除端口。只需将要排除的范围添加到多字符串值:
HKLM\System\CurrentControlSet\Services\TCPIP\Parameters\ReservedPorts
因此,就我而言,我需要使用端口 55101-55107,因此我将该文本添加到注册表值并重新启动了计算机。虽然此解决方案允许我使用这些端口,但令人失望的是我必须在我想使用它们的任何 Windows 机器上编辑注册表。另外,如果我以后要添加另一个动态端口,我将不得不重新编辑注册表。