2015-09-29 1 views
1

Я пытаюсь выполнить программный сеанс telnet в Java. Я использую commons-netTelnetClient, но я также экспериментировал с прямым сокетом. В любом случае у меня такая же проблема.Java telnet login: после загрузки имени пользователя

Я прочитал «login:», а затем отправьте имя пользователя, а затем CRLF. Тогда ничего, никакие другие данные не читаются или не написаны сервером.

Сервер telnet находится на встроенном устройстве (принтер Star), поэтому мне интересно, есть ли какие-то особые параметры, которые я не настраиваю, или которые не поддерживаются классом commons-netTelnetClient.

Я могу использовать Linux telnet без проблем, и я могу запустить свой код на сервере telnet в OSX, и он отлично работает.

TelnetClient client = new TelnetClient(); 
    client.registerNotifHandler(new TelnetNotificationHandler() { 
    @Override 
    public void receivedNegotiation(int negotiation_code, int option_code) { 
     ALog.i(this, "negotiation code: %d, option code: %d", negotiation_code, option_code); 
    } 
    }); 
    try { 
    client.addOptionHandler(new TerminalTypeOptionHandler("VT100", false, false, true, false)); 
    client.addOptionHandler(new SuppressGAOptionHandler(true, false, true, false)); 
    client.addOptionHandler(new EchoOptionHandler(true, true, true, true)); 
    } catch (InvalidTelnetOptionException e) { 
    e.printStackTrace(); 
    } 

    try { 
    FileOutputStream fos = new FileOutputStream("/sdcard/spy.out"); 
    client.registerSpyStream(fos); 
    } catch (FileNotFoundException e) { 
    e.printStackTrace(); 
    } 

    InputStream in = null; 
    PrintWriter out = null; 

    String ip = getIpAddress(p); 
    ALog.i(this, "connecting to: %s", ip); 
    try { 
    client.connect(ip); 
    in = client.getInputStream(); 
    out = new PrintWriter(client.getOutputStream(), true); 

    if (!expect(in, "login: ", 5000)) { 
     return; 
    } 
    if (!send(out, "root")) { 
     return; 
    } 
    if (!expect(in, "password: ", 5000)) { 
     return; 
    } 
    if (!send(out, "password")) { 
     return; 
    } 

Вот что expect() и send() методы,

protected boolean expect(InputStream in, String s, long timeout) { 
    ALog.i(this, "expecting: %s", s); 

    final AtomicBoolean lock = new AtomicBoolean(false); 
    final ExpectThread t = new ExpectThread(in, s, lock, timeout); 
    t.start(); 
    synchronized (lock) { 
     try { 
     lock.wait(timeout); 
     } catch (InterruptedException e) { 
     } 
    } 
    t.interrupt(); 
    return lock.get(); 
    } 

    protected boolean send(PrintWriter out, String s) { 
    out.println(s); 
    out.flush(); 
    ALog.i(this, "sent: %s", s); 
    return true; 
    } 

И вот ExpectThread,

private class ExpectThread extends Thread { 
    private final InputStream in; 
    private final String expected; 
    private final AtomicBoolean lock; 
    private final long start; 
    private final long timeout; 

    ExpectThread(InputStream in, String expected, AtomicBoolean lock, long timeout) { 
     this.in = in; 
     this.expected = expected.toLowerCase(); 
     this.lock = lock; 
     this.timeout = timeout; 
     this.start = System.currentTimeMillis(); 
    } 

    @Override 
    public void run() { 
     final StringBuilder b = new StringBuilder(); 
     final byte[] buffer = new byte[1024]; 
     int c; 

     try { 
     while (!isInterrupted() && System.currentTimeMillis() < start + timeout) { 
      ALog.i(this, "starting read ..."); 
      while ((c = in.read(buffer)) != -1) { 
      String s = new String(buffer, 0, c); 
      b.append(s.toLowerCase()); 
      ALog.i(this, "read string: %s, buffer: %s", s, b.toString()); 
      if (b.toString().contains(expected)) { 
       ALog.i(this, "found expected"); 
       lock.set(true); 
       return; 
      } 
      } 
      ALog.i(this, "waiting for read ..."); 
      SystemClock.sleep(1000); 
     } 
     } catch (IOException e) { 
     e.printStackTrace(); 
     } finally { 
     synchronized (lock) { 
      lock.notifyAll(); 
     } 
     } 
    } 
    } 

вот Wireshark PCAP провалившегося программной сессии https://drive.google.com/file/d/0B5iST80rpTN9c1RsRTNFaE5GZHM/view?usp=sharing

вот PCAP из успешного терминала (Linux телнет клиент) сессии https://drive.google.com/file/d/0B5iST80rpTN9bDZFOHhkSHlPSE0/view?usp=sharing

Я вижу, клиент Linux посылает «будет аутентифицировать», где мой код не делает. Я бы попробовал, если бы мог выяснить, как получить TelnetClient для отправки таких команд.

+0

Можете ли вы показать нам какой-нибудь код? – Thomas

+0

Попытка не делать беспорядок сообщения. Я вставил код верхнего уровня. Обратите внимание, что я тестировал это на простом эхо-сервере, который я написал, и он работает, поэтому я считаю, что нет никаких проблем с кодом чтения/записи. –

+0

Проверьте, что устройство отправляет с помощью реального клиента Telnet. Может быть, например, нет пробела после 'password:'. NB вам нужно найти 'Socket.setSoTimeout()'.Вам не нужны все эти потоки, блокировки и ожидания. – EJP

ответ

1

Вы должны отправить \r\n явно, а не через println(). Это должно быть именно то, что не делает println() в вашей системе.

Я также подозреваю, что ваш метод expect() может быть заранее. Он должен читать байт или символ за раз, чтобы этого не произошло. И, пожалуйста, попробуйте его с розеткой таймаут вместо этого Мегилле нитей и замков и ждет:

protected boolean expect(Socket socket, InputStream in, String expected, long timeout) throws IOException { 
    ALog.i(this, "expecting: %s", s); 
    long endTime = System.currentTimeMillis() + timeout; 
    byte[] buffer = new byte[8192]; 
    StringBuffer b = new StringBuffer(); 
    try 
    { 
     while (System.currentTimeMillis() < endTime) 
     { 
      socket.setSoTimeout((int)(endTime - System.currentTimeMillis())); 
      ALog.i(this, "starting read ..."); 
      int c = in.read(); 
      if (c == -1) 
      { 
       return false; 
      } 
       ALog.i(this, "read string: %s, buffer: %s", s, b.toString()); 
      b.append(Character.valueOf((char)c)); 
      if (b.toString().toLowerCase().contains(expected)) 
      { 
       ALog.i(this, "found expected"); 
       return true; 
      } 
     } 
     return false; 
    } 
    catch (SocketTimeoutException exc) 
    { 
     return false; 
    } 
} 

E & OE

+0

Я пробовал это. Это не имеет никакого значения, например, 'out.print (s +" \ r \ n ")' –

+0

Тем не менее, правильный способ сделать это. Не используйте «PrintWriter»: они проглатывают исключения. Используйте 'BufferedWriter.' – EJP

+0

Я тоже пробовал это, просто' OutputStream.write() '. Почти все примеры, которые я могу найти в Интернете, используют «PrintWriter», поэтому я переключился. –

0

Отвечая на мой собственный вопрос ...

Как я и подозревал, это была проблема с переговорами telnet с этим конкретным сервером. Я должен был использовать очень специфический эхо-обработчик опции,

client.addOptionHandler(new EchoOptionHandler(false, false, false, true)); 

Это означает принять DO ECHO, что сервер отправки. Я обнаружил это несоответствие, сравнив переговоры telnet DO/WILL между нерабочими и рабочими сессиями.

 Смежные вопросы

  • Нет связанных вопросов^_^