# Telnet-Klasse mit Hindernissen



## diabolik (11. Mrz 2009)

Hallo Freunde des guten Codes. ;o)

Ich sitze seit 2 Tagen vor einem Problem, welches ich trotz aller Mühe nicht lösen kann. Daher habe ich nun beschlossen, mir bei Profis Hilfe zu holen.

Vorgeschichte:
----------------

Ich schreibe an einem Programm, welches sich automatisch mit einem Login-Server via Telnet auf Port 23 verbinden soll. Von dort soll es sich dann mit ein paar Cisco-Routern aus meinem Netzwerk verbinden können und vorgegebene Kommandos absetzen. Das Ergebnis jage ich dann durch einen Filter und am Ende gibt's ein Ausgabe in Excel.

So weit so gut. Nun habe ich lange nach einem brauchbaren, kostenlosen Telnet-Client gesucht. Diesen habe ich nun bei Apache.org gefunden. Ich nutze hierzu die JAR-Datei commons-net-2.0.jar.

Anbei war dann auch gleich eine fertige Telnet-Anwendung als Anschauungsbeispiel. Diese habe ich mühelos zum Test in mein Programm eingebunden und auch sofort zum Laufen bekommen. 

Mein Problem:
----------------

Diese Telnet-Klasse des Beispiels basiert auf der Voraussetzung, dass sämtliche Zeichenketten über die Tastatur eingegeben werden müssen. Das ist aber genau das, was ich nicht gebrauchen kann. Ich muß aus dem laufenden Programm Befehle über irgend ein Interface an den Telnet-Thread übergeben und im Gegenzug auch jeglichen eingehenden Text über eine andere Schnittstelle mitlesen können. Und zu guter letzt muß ich den gesamten Telnet-Thread bei Bedarf mittels "interrupt()" beenden können. All das bekomme ich nicht gebacken...


Meine Frage:
--------------

Kann mir irgendwer hierbei helfen? Hat vielleicht irgendwer schon eine fertige Klasse, die genau diese Probleme löst? Nachfolgend "poste" ich Euch mal den Quellcode der Telnet-Klasse. Vielleicht könnt Ihr ja hier schon ansetzen und mir sagen, wie ich mir hier die entsprechenden Interfaces einbringen und die Klasse "interruptable" machen kann.

Wie es auch ausgehen mag, ich Danke bereits jetzt schon jedem, der versucht, mir hier behilflich zu sein!!!



```
package mrap.Controller;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.commons.net.telnet.TelnetClient;
import org.apache.commons.net.telnet.TelnetNotificationHandler;
import org.apache.commons.net.telnet.SimpleOptionHandler;
import org.apache.commons.net.telnet.EchoOptionHandler;
import org.apache.commons.net.telnet.TerminalTypeOptionHandler;
import org.apache.commons.net.telnet.SuppressGAOptionHandler;
import org.apache.commons.net.telnet.InvalidTelnetOptionException;
import java.util.StringTokenizer;


public class Telnet implements Runnable, TelnetNotificationHandler{
    static TelnetClient tc = null;

    public static void connectToServer(String remoteIP) throws IOException
    {
        FileOutputStream fout = null;
        int remotePort = 23;

        try
        {
            fout = new FileOutputStream ("spy.log", true);
        }
        catch (Exception e)
        {
            System.err.println(
                "Exception while opening the spy file: "
                + e.getMessage());
        }

        tc = new TelnetClient();

        TerminalTypeOptionHandler ttopt = new TerminalTypeOptionHandler("VT100", false, false, true, false);
        EchoOptionHandler echoopt = new EchoOptionHandler(true, false, true, false);
        SuppressGAOptionHandler gaopt = new SuppressGAOptionHandler(true, true, true, true);

        try
        {
            tc.addOptionHandler(ttopt);
            tc.addOptionHandler(echoopt);
            tc.addOptionHandler(gaopt);
        }
        catch (InvalidTelnetOptionException e)
        {
            System.err.println("Error registering option handlers: " + e.getMessage());
        }

        while (true)
        {
            boolean end_loop = false;
            try
            {
                tc.connect(remoteIP, remotePort);

                Thread reader = new Thread (new Telnet());
                tc.registerNotifHandler(new Telnet());
                reader.start();
                OutputStream outstr = tc.getOutputStream();

                byte[] buff = new byte[1024];
                int ret_read = 0;

                do
                {
                    try
                    {
                        ret_read = System.in.read(buff);

                        if(ret_read > 0)
                        {
                            if((new String(buff, 0, ret_read)).startsWith("AYT"))
                            {
                                try
                                {
                                   tc.sendAYT(5000);
                                }
                                catch (Exception e)
                                {
                                    System.err.println("Exception waiting AYT response: " + e.getMessage());
                                }
                            }
                            else if((new String(buff, 0, ret_read)).startsWith("OPT"))
                            {   /*
                                 for(int ii=0; ii<25; ii++)
                                    System.out.println("Local Option " + ii + ":" + tc.getLocalOptionState(ii) + " Remote Option " + ii + ":" + tc.getRemoteOptionState(ii));
                               */
                            }
                            else if((new String(buff, 0, ret_read)).startsWith("REGISTER"))
                            {
                                StringTokenizer st = new StringTokenizer(new String(buff));
                                try
                                {
                                    st.nextToken();
                                    int opcode = (new Integer(st.nextToken())).intValue();
                                    boolean initlocal = (new Boolean(st.nextToken())).booleanValue();
                                    boolean initremote = (new Boolean(st.nextToken())).booleanValue();
                                    boolean acceptlocal = (new Boolean(st.nextToken())).booleanValue();
                                    boolean acceptremote = (new Boolean(st.nextToken())).booleanValue();
                                    SimpleOptionHandler opthand = new SimpleOptionHandler(opcode, initlocal, initremote,
                                                                    acceptlocal, acceptremote);
                                    tc.addOptionHandler(opthand);
                                }
                                catch (Exception e)
                                {
                                    if(e instanceof InvalidTelnetOptionException)
                                    {
                                        System.err.println("Error registering option: " + e.getMessage());
                                    }
                                    else
                                    {
                                        System.err.println("Invalid REGISTER command.");
                                        System.err.println("Use REGISTER optcode initlocal initremote acceptlocal acceptremote");
                                        System.err.println("(optcode is an integer.)");
                                        System.err.println("(initlocal, initremote, acceptlocal, acceptremote are boolean)");
                                    }
                                }
                            }
                            else if((new String(buff, 0, ret_read)).startsWith("UNREGISTER"))
                            {
                                StringTokenizer st = new StringTokenizer(new String(buff));
                                try
                                {
                                    st.nextToken();
                                    int opcode = (new Integer(st.nextToken())).intValue();
                                    tc.deleteOptionHandler(opcode);
                                }
                                catch (Exception e)
                                {
                                    if(e instanceof InvalidTelnetOptionException)
                                    {
                                        System.err.println("Error unregistering option: " + e.getMessage());
                                    }
                                    else
                                    {
                                        System.err.println("Invalid UNREGISTER command.");
                                        System.err.println("Use UNREGISTER optcode");
                                        System.err.println("(optcode is an integer)");
                                    }
                                }
                            }
                            else if((new String(buff, 0, ret_read)).startsWith("SPY"))
                            {
                                try
                                {
                                    tc.registerSpyStream(fout);
                                }
                                catch (Exception e)
                                {
                                    System.err.println("Error registering the spy");
                                }
                            }
                            else if((new String(buff, 0, ret_read)).startsWith("UNSPY"))
                            {
                                tc.stopSpyStream();
                            }
                            else
                            {
                                try
                                {                                        
                                        System.out.println("Sende: " + new String (buff, 0 , ret_read));
                                        outstr.write(buff, 0 , ret_read);
                                        outstr.flush();
                                }
                                catch (Exception e)
                                {
                                        end_loop = true;
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        System.err.println("Exception while reading keyboard:" + e.getMessage());
                        end_loop = true;
                    }
                }
                while((ret_read > 0) && (end_loop == false));

                try
                {
                    System.out.println("disconnect connect");
                    tc.disconnect();
                    reader.interrupt();
                }
                catch (Exception e)
                {
                          System.err.println("Exception while disconnecting:" + e.getMessage());
                          tc.disconnect();
                          reader.interrupt();
                }
            }
            catch (Exception e)
            {
                    System.err.println("Exception while connecting:" + e.getMessage());
            }
        }
    }


    /***
     * Callback method called when TelnetClient receives an option
     * negotiation command.
     * <p>
     * @param negotiation_code - type of negotiation command received
     * (RECEIVED_DO, RECEIVED_DONT, RECEIVED_WILL, RECEIVED_WONT)
     * <p>
     * @param option_code - code of the option negotiated
     * <p>
     ***/
    public void receivedNegotiation(int negotiation_code, int option_code)
    {
        String command = null;
        if(negotiation_code == TelnetNotificationHandler.RECEIVED_DO)
        {
            command = "DO";
        }
        else if(negotiation_code == TelnetNotificationHandler.RECEIVED_DONT)
        {
            command = "DONT";
        }
        else if(negotiation_code == TelnetNotificationHandler.RECEIVED_WILL)
        {
            command = "WILL";
        }
        else if(negotiation_code == TelnetNotificationHandler.RECEIVED_WONT)
        {
            command = "WONT";
        }
        System.out.println("Received " + command + " for option code " + option_code);
   }

    /***
     * Reader thread.
     * Reads lines from the TelnetClient and echoes them
     * on the screen.
     ***/
    public void run()
    {
        InputStream instr = tc.getInputStream();

        try
        {
            byte[] buff = new byte[1024];
            int ret_read = 0;

            do
            {
                ret_read = instr.read(buff);
                if(ret_read > 0)
                {
                    System.out.print("Empfange: " + new String(buff, 0, ret_read));
                }
            }
            while (ret_read >= 0);
        }
        catch (Exception e)
        {
            System.err.println("Exception while reading socket:" + e.getMessage());
        }

        try
        {
            tc.disconnect();
            System.out.println("disconnect run");
        }
        catch (Exception e)
        {
            System.err.println("Exception while closing telnet:" + e.getMessage());
        }
    }
}
```


----------



## derMartin (12. Mrz 2009)

Hallo,

die Frage dabei ist, ob es nicht einfach reicht, die normale Java-Socket-Klasse zu benutzen.
Einfach einen Socket auf Port 23 öffnen und dann via BuffererdReader und BufferedWriter, die Kommandos
und den Response an Hand der Telnet RFCs zu verarbeiten.

RFC 854 (rfc854) - Telnet Protocol Specification

Gruß
/martin


----------



## diabolik (12. Mrz 2009)

Hallo Martin,

das mit dem JAVA-Socket ist nie mein Problem gewesen. Aber der Server, mit welchem ich in Kontakt treten möchte, startet beim Telnet-Connect zunächst mal eine "Negotiation"! Und da ich hier echt überhaupt keinen Plan habe, hatte ich versucht, dass ganze mit der fertigen Telnet-Klasse zu umgehen. Denn die macht das alles automatisch.

Jedoch habe ich mir Deinen Eintrag als Anlass für eine erneute Lösungssuche ohne das hier besprochene Telnet-Paket genommen. Und siehe da, ich habe endlich ein fertiges "Negotitation"-Modul gefunden. Nun klappts auch mit meinem Server und alles andere ist nur noch schmückendes Beiwerk!

Daher: "Danke für den Denkanstoss!"

Gruß
Maik


----------

