sencha app watch
然后过了一段时间,我退出并再次启动它,我得到一个警告,端口1841已经在使用中,然后它就因为这个原因使用了一个随机端口。
端口1841已在使用中。改用动态端口。
无论我多久终止并重新启动一次该命令,它都拒绝接收端口1841。。。直到我第一次杀了它1分钟后。然后它将很高兴地再次使用端口1841(直到我下次退出它…)。
奇怪的是,这个端口实际上没有被使用。在这一分钟内,我可以在该端口上启动任何其他操作。例如http服务器
http-server -p 1841
sencha应用程序手表
在时间范围内,它声称该端口仍在使用中。。。
lsof
也没有发现任何东西阻塞端口:
kill: not enough arguments
sencha app watch --port 1841
而不是
没什么区别。
因此,我使用Procyon反编译了sencha.jar并发现:
if (this._port > 0 && !NetworkUtil.isPortAvailable(this._port)) {
WebServerTask._logger.warn("Port {} already in use. Using dynamic port instead.", (Object)this._port);
this._port = 0;
}
isPortAvailable
public static synchronized boolean isPortAvailable(final int port) {
return _isPortAvailable(port, "127.0.0.1");
}
_isPortAvailable
:
private static boolean _isPortAvailable(final int port, final String address) {
return _socketChannelPortAvailable(port, address) && _serverSocketPortAvailable(port, address);
}
_serverSocketPortAvailable
:
private static boolean _serverSocketPortAvailable(final int p, final String address) {
ServerSocket srv = null;
try {
srv = new ServerSocket();
srv.setReuseAddress(false);
if (!StringUtil.isNullOrEmpty(address)) {
srv.bind(new InetSocketAddress(address, p));
}
else {
srv.bind(new InetSocketAddress(p));
}
return true;
}
catch (Exception ex2) {
return false;
}
finally {
if (srv != null) {
try {
srv.close();
}
catch (Exception ex) {
throw BasicException.raise(ex);
}
}
}
}
_socketChannelPortAvailable with 2 parameters
:
private static boolean _socketChannelPortAvailable(final int p, final String address) {
return _socketChannelPortAvailable(p, address, true);
}
_socketChannelPortAvailable with 3 parameters
:
private static boolean _socketChannelPortAvailable(final int p, final String address, final boolean reuseAddr) {
ServerSocketChannel srv = null;
try {
srv = ServerSocketChannel.open();
if (!reuseAddr) {
srv.setOption(StandardSocketOptions.SO_REUSEADDR, false);
}
if (!StringUtil.isNullOrEmpty(address)) {
srv.bind(new InetSocketAddress(address, p));
}
else {
srv.bind(new InetSocketAddress(p));
}
return true;
}
catch (Exception ex) {
return false;
}
finally {
if (srv != null) {
try {
srv.close();
}
catch (Exception ex2) {}
}
}
}
ServerSocket
,
ServerSocketChannel
,
InetSocketAddress
StandardSocketOptions
似乎来自Java标准库:
import java.net.StandardSocketOptions;
import java.nio.channels.ServerSocketChannel;
import java.net.SocketAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
但这一切看起来都应该对我有用。
你知道这里出了什么问题吗?
编辑
:
有没有可能
if (!reuseAddr) {
srv.setOption(StandardSocketOptions.SO_REUSEADDR, false);
}
到
srv.setOption(StandardSocketOptions.SO_REUSEADDR, reuseAddr);
这会解决问题吗?