У нас возникли проблемы с попыткой реализовать пул SftpConnections для нашего приложения.
В настоящее время мы используем SSHJ
(Schmizz) в качестве транспортной библиотеки и сталкиваемся с проблемой, которую мы просто не можем имитировать в нашей среде разработки (но ошибка продолжает проявляться случайным образом в производстве, иногда через три дня, иногда после 10 минут).
Проблема заключается в том, что при попытке отправить файл через SFTP поток блокируется в методе init
из класса schmizz 'TransportImpl
:
@Override
public void init(String remoteHost, int remotePort, InputStream in, OutputStream out)
throws TransportException {
connInfo = new ConnInfo(remoteHost, remotePort, in, out);
try {
if (config.isWaitForServerIdentBeforeSendingClientIdent()) {
receiveServerIdent();
sendClientIdent();
} else {
sendClientIdent();
receiveServerIdent();
}
log.info("Server identity string: {}", serverID);
} catch (IOException e) {
throw new TransportException(e);
}
reader.start();
}
isWaitForServerIdentBeforeSendingClientIdent для нас ЛОЖЬ, поэтому, прежде всего, клиент (мы) отправляем нашу идентификацию, как показано в журналах:
"Идентификатор клиента String: blabla"
Затем он поворачивается для receiveServerIdent
:
private void receiveServerIdent() throws IOException
{
final Buffer.PlainBuffer buf = new Buffer.PlainBuffer();
while ((serverID = readIdentification(buf)).isEmpty()) {
int b = connInfo.in.read();
if (b == -1)
throw new TransportException("Server closed connection during identification exchange");
buf.putByte((byte) b);
}
}
Нить никогда не получает контроль, так как сервер никогда не отвечает своей личностью. Кажется, что код застрял в этом цикле While. Никаких тайм-аутов или исключений SSH не выбрасывается, мой клиент просто ждет навсегда, и поток заходит в тупик.
Это метод readIdentification
:
private String readIdentification(Buffer.PlainBuffer buffer)
throws IOException {
String ident = new IdentificationStringParser(buffer, loggerFactory).parseIdentificationString();
if (ident.isEmpty()) {
return ident;
}
if (!ident.startsWith("SSH-2.0-") && !ident.startsWith("SSH-1.99-"))
throw new TransportException(DisconnectReason.PROTOCOL_VERSION_NOT_SUPPORTED,
"Server does not support SSHv2, identified as: " + ident);
return ident;
}
Похоже, что входной поток ConnectionInfo никогда не получает данные для чтения, как если бы сервер закрывал соединение (даже если, как было сказано ранее, исключение не генерируется).
Я попытался смоделировать эту ошибку, насытив согласование, закрывая сокеты при подключении, используя conntrack, чтобы убить установленные соединения, пока выполняется рукопожатие, но не везет вообще, поэтому любая помощь будет ВЫСОКО оценили.
:)