Rebex


Telnet Tutorial

Applies to: Rebex Total Pack, Rebex SSH Pack, Rebex Terminal Emulation

Table of content

#About Rebex Telnet

Rebex Telnet for .NET is a versatile component for .NET languages (such as C# or VB.NET). It makes it possible to access remote servers from your application using the Telnet protocol.

Please note that telnet communication is not secured. Consider using the SSH Shell component instead when SSH is available at the remote server.

back to top...


#Namespaces and assemblies

To use the features of Rebex Telnet for .NET described here, you have to reference the Rebex.Telnet.dll, Rebex.Common.dll, Rebex.Networking.dll and Rebex.TerminalEmulation.dll assemblies in your project. These contain Telnet, Shell, TerminalControl/TelnetTerminalControl, VirtualTerminal and other classes in Rebex.Net and Rebex.TerminalEmulation namespaces.

In your source files, import the following namespaces:

C#

using Rebex.Net;
using Rebex.TerminalEmulation;

VB.NET

Imports Rebex.Net
Imports Rebex.TerminalEmulation;

back to top...


#Telnet basics

There are three possible ways of using the Telnet component. Each is suitable for a different scenario:

  1. Scripting – when you need to script the telnet communication (send a command and receive a response), Shell class is suitable. To create an instance of Shell object, just call the Telnet.StartShell() method.
  2. User interface – when you need to provide graphical user interface to manage the server using the Telnet protocol, drag & drop the TerminalControl Windows Forms control to your application and use the TerminalControl.Bind(Telnet) method. Alternatively you can drag&drop the TelnetTerminalControl, set its properties and call the TelnetTerminalControl.Connect() method.
  3. Virtual screen-less terminal – when no user interaction is needed and/or it is not necessary or desirable to display the terminal screen content in real time, all you need is the VirtualTerminal class. To create an instance of VirtualTerminal object, call the Telnet.StartVirtualTerminal() method.

Unlike most Rebex components, the Telnet class has no Connect, Login or Disconnect methods. A new connection is made each a time new instance of Shell or VirtualTerminal object is requested or when the Bind method of the TerminalControl is called. The reason for this is that unlike most other protocols, authentication is not a part of the Telnet protocol and there are basically no general-purpose commands to be called for the Telnet session.

To authenticate to the server, you need to know whether the server you are connecting to requires any authentication and how it is performed. It is then your responsibility to authenticate properly. This will be covered later in this tutorial.

To disconnect from the server, just call the Close method of the Shell class or the Unbind method if you are using the VirtualTerminal or TerminalControl class. With TelnetTerminalControl class, use the Disconnect method.

Scripting - requesting a Shell

C#

// create the client
Telnet client = new Telnet("servername");

// start the Shell
Shell shell = client.StartShell();

// send commands and read responses
// ...

// close the shell
shell.Close();

VB.NET

' create the client
Dim client As New Telnet("servername")

' start the Shell
Dim shell As Shell = client.StartShell()

' send commands and read responses
' ...

' close the shell
shell.Close()

User interface - binding a TerminalControl

C#

// create the client
Telnet client = new Telnet("servername");

// bind the TerminalControl
// (terminalControl1 is a WinForm control dragged & dropped on the Form)
terminalControl1.Bind(client);

VB.NET

' create the client
Dim client As New Telnet("servername")

' bind the TerminalControl
' (terminalControl1 is a WinForm control dragged & dropped on the Form)
terminalControl1.Bind(client)

User interface - connecting a TelnetTerminalControl

C#

// assign the ServerName to the TelnetTerminalControl
// (telnetTerminalControl1 is a WinForm control dragged & dropped on the Form)
telnetTerminalControl1.ServerName = "servername";

// connect the TelnetTerminalControl to the specified server
telnetTerminalControl1.Connect();

VB.NET

' assign the ServerName to the TelnetTerminalControl
' (telnetTerminalControl1 is a WinForm control dragged & dropped on the Form)
telnetTerminalControl1.ServerName = "servername"

' connect the TelnetTerminalControl to the specified server
telnetTerminalControl1.Connect()

Screen-less terminal - starting a VirtualTerminal

C#

// create the client
Telnet client = new Telnet("servername");

// start the VirtualTerminal
VirtualTerminal terminal = client.StartVirtualTerminal();

// send commands and process responses
// ...

// dispose it to close the connection and release all resources
terminal.Dispose();

VB.NET

' create the client
Dim client As New Telnet("servername")

' start the VirtualTerminal
Dim terminal As VirtualTerminal = client.StartVirtualTerminal()

' send commands and process responses
' ...

' Unbind the VirtualTerminal for closing the connection
' (VirtualTerminal stay ready for later using)
terminal.Unbind()

' or Dispose it for closing the connection and releasing all resources
terminal.Dispose()

back to top...


#Using shell

The first way of using the Telnet component - scripting - is handled by the Shell class that is initialized using the Telnet.StartShell method. This returns a new instance of Shell that can be used to send commands and read responses using several different methods.

A shell session can be used to run multiple commands. However, detecting where the response of one command ends is tricky - Unix shells were obviously not designed to be used programmatically and providing a shell API is quite a challenge. For this reason, prompt-base command response ending detection was implemented.

This can be used with most shells, but the prompt used to detect command response endings has to be set manually to match the prompt at the remote server. This means that a remote server's prompt has to be known before reading the first response (the welcome message). The prompt can be specified using one of the following methods:

  1. Simple text - Matches an exact phrase.
    If the remote server prompt is the server hostname ending with '#' and a whitespace, the "hostname# " string can be used to match the prompt.
    Note that this type of prompt requires that server prompt to remain constant during the whole session. In practice, prompts of many Unix-based shells contain the current path, making it necessary to use one of the other prompt specification metods.
  2. Wildcards - Matches a phrase with wildcards.
    If the server prompt can vary slightly, it is possible to utilize wildcards to handle prompt changes or variants. This type has to be prefixed with the "mask:" string when being set. Available wildcards:
    '?' - matches any one character.
    '*' - matches any character sequence including zero length sequence.
    Let's say the server's prompt is "username@hostname:currentPath$ " (as in most Unix shells), where currentPath changes during the session and the '$' character can change to '#' if logged as the "root" superuser (administrator).
    In this case, "mask:userName@serverName:*? " string can be used to match the prompt.
  3. Regular expression - Matches a regular expression.
    This is the most versatile prompt expression type. It uses regular expression to match command response endings. This type has to be prefixed with the "regex:" string when being set. Let's say the server's prompt is "username@hostname:currentPath$ " (the same as above), where currentPath changes during the session and the '$' character can change to '#' if logged as the "root" superuser (administrator).
    In this case, "regex:(userName[@]serverName[:].*[$])|(serverName[:].*[#]) " string can be used to match the prompt.
    Regular expressions are not the topic of this tutorial, but lots of information about them can be found elsewhere.

back to top...


#Interactive commands

Some shell commands require user input and this makes them hard to use programmatically. Whenever possible, a non-interactive mode or another command should be used. However, if this is not an option, you can still use interactive commands with a bit of additional work - all you need to know is the string that indicates the command is waiting for user input. For example, this is how to handle the interactive version of the rm command:

C#

// see above for how to get an instance of the Shell class

// start the 'rm' command
shell.SendCommand("rm -i /tmp/*");

// repeat while the command is running
while (shell.IsRunning)
{
    // read response until end or until '? ' is encountered
    string result = shell.ReadAll("? ");

    // if '? ' was encountered, send Y for yes
    if (result.EndsWith("? "))
    {
        shell.SendCommand("y");
    }
}

VB.NET

' see above for how to get an instance of the Shell class

' start the 'rm' command
shell.SendCommand("rm -i /tmp/*")

' repeat while the command is running
While shell.IsRunning
    ' read response until end or until '? ' is encountered
    Dim result As String = shell.ReadAll("? ")

    ' if '? ' was encountered, send Y for yes
    If result.EndsWith("? ") Then
        shell.SendCommand("y")
    End If
End While

The loop simply detects all questions ending with "? " and answers 'y' to them.

back to top...


#Custom authentication

Authentication is not a part of the Telnet protocol and only occurs once a telnet session has been established. Some servers don't require any authentication at all, others ask for a username and password. Other behavior is rare but perfectly possible as well.

To authenticate to the server, you need to know whether the server you are connecting to requires any authentication and how it is performed. It is then your responsibility to authenticate properly.

In this tutorial, we will show how to authenticate against a common Telnet server using Rebex Telnet for .NET component. The authentication is performed using the alternative question prompts as described in the Interactive commands tutorial.

Let's suppose the Telnet server prints some welcome message and prompts for the username by sending "Enter the login: " message. After entering the login, it prompts for the password by sending the "Password: " message. If the credentials were correct, it prints the "Login successful" message and other information. Finally, it also prints the prompt in the form of "username@servername:path$ " and waits for the user input.

C#

// connection values
string serverName = "TelnetTestServer";
string userName = "tester";
string password = "test";

// create the client
Telnet client = new Telnet(serverName);

// start the Shell
Shell shell = client.StartShell();

// !!!
// set the server's prompt (it strongly depends on the server)
// how to set the server's prompt see the "Using shell" tutorial at
// http://www.rebex.net/telnet.net/tutorial-telnet.aspx#using-shell
// !!!
shell.Prompt = string.Format("mask:{0}@{1}:*$ ", userName, password);

// read welcome message until login prompt appears
shell.ReadAll("ogin: ");

// send the username to the remote server
shell.SendCommand(userName);

// read the response until password prompt appears
shell.ReadAll("ssword: ");

// send the password to the remote server
shell.SendCommand(password, true);

// read the response until regular shell prompt appears
string loginMessage = shell.ReadAll();

// check if the server replied with expected response
if (!loginMessage.StartsWith("Login successful"))
    throw new Exception("Authentication failed.");

// send commands and read responses
// ...

// close the shell
shell.Close();

VB.NET

' connection values
Dim serverName As String = "TelnetTestServer"
Dim userName As String = "tester"
Dim password As String = "test"

' create the client
Dim client As New Telnet(serverName)

' start the Shell
Dim shell As Shell = client.StartShell()

' !!!
' set the server's prompt (it strongly depends on the server)
' how to set the server's prompt see the "Using shell" tutorial at
' http://www.rebex.net/telnet.net/tutorial-telnet.aspx#using-shell
' !!!
shell.Prompt = String.Format("mask:{0}@{1}:*$ ", userName, serverName)

' read welcome message until login prompt appears
shell.ReadAll("ogin: ")

' send the username to the remote server
shell.SendCommand(userName)

' read the response until password prompt appears
shell.ReadAll("ssword: ")

' send the password to the remote server
shell.SendCommand(password, True)

' read the response until regular shell prompt appears
Dim loginMessage As String = shell.ReadAll()

' check if the server replied with expected response
If Not loginMessage.StartsWith("Login successful") Then
    Throw New Exception("Authentication failed.")
End If

' send commands and read responses
' ...

' close the shell
shell.Close()

The best way to determine how the authentication of your Telnet server works and which messages it sends is to connect to the server using the WinForm client sample and check its output. Then you can write an appropriate authentication code using the Shell object. Please note that prompt (and alternative question prompt) detection is case sensitive.

back to top...


#Terminal emulation with Windows Forms control

The TerminalControl and TelnetTerminalControl classes make it very simple to add terminal emulation capabilities to your applications. Even writing a full-fledged Telnet client in a few lines of code is trivial:

C#

// get the telnet terminal control object that was added
// to the Form using the Visual Studio designer
TelnetTerminalControl terminal = this.telnetTerminalControl1;

// set Telnet server address
terminal.ServerName = serverName;

// connect to the server
terminal.Connect();

// ...

// disconnect from the server
terminal.Disconnect();

VB.NET

' get the telnet terminal control object that was added
' to the Form using the Visual Studio designer
Dim terminal As TelnetTerminalControl = Me.telnetTerminalControl1

' set telnet server address
terminal.ServerName = serverName

' connect to the server
terminal.Connect()

' ...

' disconnect from the server
terminal.Disconnect()

In this code snippet, the TelnetTerminalControl class was used. This is an extension of the TerminalControl class, which is independent of the Telnet protocol and component and might be used for other purposes as well, as demonstrated by the ANSI Player sample that uses it for a file-based ANSI communication replay. For basic usage, however, check the Simple Telnet Client and Windows Forms Telnet Client samples instead.

back to top...


#Virtual terminal emulation

In some scenarios where no user interaction is needed or desired and/or it is not necessary or desirable to display the terminal screen content in real time, a Windows Forms based terminal emulator might not be the right choice. The VirtualTerminal class may be more suitable. For example, there is no need to use WinFormClient if all you need is to save the content of the terminal screen into a file:

C#

// create the client
Telnet client = new Telnet(serverName);

// create a virtual terminal
VirtualTerminal terminal = new VirtualTerminal(80, 25);

// bind the virtual terminal to the Telnet client object
terminal.Bind(client);

// send the 'df' command to the server
// please note that you also have to send the 'enter' - often the '\r' character
terminal.SendToServer("df\r");

// receive and process any server response
TerminalState state;
do
{
    // wait 5 seconds for the response
    state = terminal.Process(5000);

    // if there was a response, try processing more
} while (state == TerminalState.DataReceived);

// save the content of the virtual terminal screen to a file
terminal.Save("terminal.png", TerminalCaptureFormat.Png);

// unbind the terminal to close the connection
// it's still ready for futher use (it can be bound to a client again)
terminal.Unbind();

// ...

// dispose it to release all resources
terminal.Dispose();

VB.NET

' create the client
Dim client As New Telnet(serverName)

' create a virtual terminal
Dim terminal As New VirtualTerminal(80, 25)

' bind the virtual terminal to the SSH client object
terminal.Bind(client)

' send the 'df' command to the server
' please note that you also have to send the 'enter' - often the vbCr character
terminal.SendToServer("df" & vbCr)

' receive and process any server response
Dim state As TerminalState
Do
    ' wait 5 seconds for the response
    state = terminal.Process(5000)

    ' if there was a response, try processing more
Loop While state = TerminalState.DataReceived

' save the content of the virtual terminal screen to a file
terminal.Save("terminal.png", TerminalCaptureFormat.Png)

' unbind the terminal to close the connection
' it's still ready for futher use (it can be bound to a client again)
terminal.Unbind()

' ...

' dispose it to release all resources
terminal.Dispose()

back to top...


#Terminal emulation options

The TelnetTerminalControl/TerminalControl and VirtualTerminal classes have lots of options to make them compatible with lots of different terminals. For more information about these, check out the documentation for the TerminalOptions class or the Winform Telnet Client sample.

C#

// create a virtual terminal
VirtualTerminal terminal = new VirtualTerminal(80, 25);

// initialize the options class and set some options
TerminalOptions options = new TerminalOptions();
options.TerminalName = "xterm";
options.FunctionKeysMode = FunctionKeysMode.Linux;
options.Encoding = System.Text.Encoding.GetEncoding("iso-8859-1");

// assign the options
terminal.Options = options;

VB.NET

' create a virtual terminal
Dim terminal As New VirtualTerminal(80, 25)

' initialize the options class and set some options
Dim options As New TerminalOptions()
options.TerminalName = "xterm"
options.FunctionKeysMode = FunctionKeysMode.Linux
options.Encoding = System.Text.Encoding.GetEncoding("iso-8859-1")

' assign the options
terminal.Options = options

back to top...


#Recording communication

The TerminalControl and VirtualTerminal classes have a useful and unique feature - communication recording. This makes it possible to save a complete Telnet session into a file and replay it later using our ANSI Player application.

C#

// get the terminal control object
TerminalControl terminal = this.terminalControl1;

// set the recorder to a file-based stream writer
terminal.Recorder = System.IO.File.AppendText("recording.ans");

// ...

VB.NET

' get the terminal control object
Dim terminal As TerminalControl = Me.terminalControl1

' set the recorder to a file-based stream writer
terminal.Recorder = System.IO.File.AppendText("recording.ans")

' ...

back to top...


Back to tutorial list...