Telnet client library
© Copyright 2004, 2005 dr. Cristiano Sadun under LGPL
SourceForge Logo

1. Purpose

This library allows easy handling of programmatic telnet conversations in the Java™ programming language, i.e. situations where the only (or preferred) interface to a system consists of a set of shell commands to be executed after a successful login via telnet.

This library is not a graphical telnet client. There are many Java™ GUI clients for telnet out there, so there is no need for another one.

2. Packaging

The library is a part of my Utility classes and doesn't come in a separate package. However, the main classes are the following :

and any dependent classes can be easily extracted by using pack or simply downloading the source from CVS.

3. Quick start

The high level idea of a command based conversation implies three phases:

The library supports this usage sequence by using, for login:
     // Create a socket to the host
     Socket s = new Socket(telnetHost, 23);
     // Create a UnixLoginHandler object over the socket to login to the host
     UnixLoginHandler handler = new UnixLoginHandler UnixLoginHandler(s);
     // Create a TelnetInputStreamConsumer object over the socket by logging in to the host
     TelnetInputStreamConsumer is = handler.doLogin("user","password");
In order to carry on the conversation, a command is issued by simply sending it on the socket's outputstream (and using the telnet newline sequence \r\n):
     String command="print hello"; // an imaginary "print" command available on the telnet interface
     PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream()), true);
     pw.print(command+"\r\n");

If the session appears to hang after login, avoid to wrap the StreamWriter into a PrintWriter and instead run an explicit flush() at the end:

     Writer w = new OutputStreamWriter(s.getOutputStream());
     w.print(command+"\r\n");
     w.flush();

Usually, a command is expected to answer with a certain result and or within a certain timeout. TelnetInputStreamConsumer offers methods that directly implement some interpretation strategies (consumeInput(long) for consuming all input within a timeout, consumeInput(java.util.regex.Pattern) for consuming input until a regular expression is matched, etc).

The most flexible way to define an interpretation strategy is by instantiating one or more criteria to define whether or not a certain command has been successful or has failed, combine them together by using a composite criterium (or any other of the predefined criterium classes) if necessary and use consumeByCriteria to consume input until a criterium is met.

For example:

     // Create the success/failure criteria and make a composite one
     TelnetInputStreamConsumer.Criterium success = new TelnetInputStreamConsumer.ContainsStringCriterium("print ok");
     TelnetInputStreamConsumer.Criterium failure = new TelnetInputStreamConsumer.ContainsStringCriterium("ERROR");
     TelnetInputStreamConsumer.CompositeCriterium expectedResults =	new TelnetInputStreamConsumer.OrCriterium(
       new TelnetInputStreamConsumer.Criterium[] { success, failure }
     );

     is.setConsumptionOperationsTimeout(10000); // We set a timeout of 10 secs anyway, in case the host blocks

     is.consumeByCriteria(expectedResults); // The actual output from the telnet host is returned here, so if necessary
                                            // it can be saved to be used later

     if (expectedResults.getHoldingCriterium() == success) {
       ..everything ok...
     } else {
       ..error...
     }
Once done with the conversation, the logout operation is performed by
     handler.doLogout(); // Use the default logout sequence
which also closes the socket.

4. More details

More details on the specifics can be found directly in the javadoc documentation of the classes. Specifically, there are methods to alter how the login/logout sequences are performed, details on exceptions raised by the various methods etc.