Когда я запускаю sencha app watch
, а затем через некоторое время я выхожу из него и запускаю его снова, я получаю предупреждение о том, что порт 1841 уже используется, а затем он просто использует случайный порт из-за этого.
Порт 1841 уже используется. Вместо этого используется динамический порт.
Независимо от того, как часто я убиваю и перезапускаю эту команду, она отказывается принимать порт 1841 ... пока не пройдет около 1 минуты с тех пор, как я убил его в первый раз. Тогда он снова с радостью примет порт 1841 (пока я не выйду из него в следующий раз ...).
Странно то, что порт на самом деле не используется. За этот минутный промежуток времени я могу просто запустить что-нибудь еще на этом порту. Например, http-сервер http-server -p 1841
работает просто отлично. Но когда я выхожу из http-сервера и пробую другой sencha app watch
в течение определенного периода времени, он утверждает, что порт все еще используется ...
lsof
также не находит ничего, что блокирует порт:
# lsof -ti:1841 -sTCP:LISTEN | xargs kill
kill: not enough arguments
Запуск sencha app watch --port 1841
вместо sencha app watch
без разницы.
Итак, я декомпилировал sencha.jar, используя Procyon, и нашел это:
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;
Но все это выглядит так, как будто это должно работать для меня.
Есть идеи, что здесь происходит не так?
Моя версия SenchaCmd - 6.5.3.6 и я в Linux.
Редактировать
Возможно ли, что изменение
if (!reuseAddr) {
srv.setOption(StandardSocketOptions.SO_REUSEADDR, false);
}
до
srv.setOption(StandardSocketOptions.SO_REUSEADDR, reuseAddr);
решит проблему?