Rebex

Skip to content, Skip to navigation




Telnet Tutorial

Back to tutorial list...

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.Net.Telnet.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), Shellclass 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...


# 

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

// start the Shell to send commands and read responses 
Shell shell = client.StartShell();

// set the prompt of the remote server's shell first (it depends on the server) 
// you have to know it for each server you are connecting to 
// (e.g. our server use as a prompt server name ended with # and space) 
shell.Prompt = "servername# ";

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

// close the shell 
shell.Close();

 

back to top...


# 

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

' start the Shell to send commands and read responses 
Dim shell As Shell = client.StartShell()

' set the prompt of the remote server's shell first (it depends on the server) 
' you have to know it for each server you are connecting to 
' (e.g. our server use as a prompt server name ended with # and space) 
shell.Prompt = "servername# "

' send commands and read responses 
' ... 

' close the shell 
shell.Close()

 

back to top...


# 

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

// start the Shell to send commands and read responses 
Shell shell = client.StartShell();

// set the prompt of the remote server's shell first 
shell.Prompt = "mask:username@servername:*? ";

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

// close the shell 
shell.Close();

 

back to top...


# 

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

' start the Shell to send commands and read responses 
Dim shell As Shell = client.StartShell()

' set the prompt of the remote server's shell first 
shell.Prompt = "mask:username@servername:*? "

' send commands and read responses 
' ... 

' close the shell 
shell.Close()

 

back to top...


# 

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

// start the Shell to send commands and read responses 
Shell shell = client.StartShell();

// set the prompt of the remote server's shell first 
shell.Prompt = @"regex:(username@servername:.*[$])|(servername:.*#) ";

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

// close the shell 
shell.Close();

 

back to top...


# 

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

' start the Shell to send commands and read responses 
Dim shell As Shell = client.StartShell()

' set the prompt of the remote server's shell first 
shell.Prompt = "regex:(username@servername:.*[$])|(servername:.*#) "

' send commands and read responses 
' ... 

' close the shell 
shell.Close()

Following table lists some commonly-used prompts on different operating systems.

Unix
Actual prompt:user2@server05:/etc$
Shell prompt string: "user2@server05:/etc$ "
Shell prompt mask:"mask:user2@server05:*$ "
Shell prompt regex:"regex:user2@server05:.*[$] "


Actual prompt:server05:/etc#
Shell prompt string: "server05:/etc# "
Shell prompt mask:"mask:server05:*# "
Shell prompt regex:"regex:server05:.*# "


Actual prompt:{user2@server05}[1]
Shell prompt string: "{user2@server05}[1] "
Shell prompt mask:"mask:{*@*}[*] "
Shell prompt regex:@"regex:{.*@.*}\[.*] "


Actual prompt:[root@server05 /etc]#
Shell prompt string: "[root@server05 /etc]# "
Shell prompt mask:"mask:[*@* *]# "
Shell prompt regex:@"regex:\[.*@.* .*]# "


Windows
Actual prompt:C:\Documents and Settings\user2>
Shell prompt string: @"C:\Documents and Settings\user2> "
Shell prompt mask:@"mask:?:\*> "
Shell prompt regex:@"regex:[A-Z]:\\.*> "


Lucent CellPipe ADSL modem
Actual prompt:<CR>$
Shell prompt string: - (not possible) -
Shell prompt mask:- (not possible) -
Shell prompt regex: C#: "regex:^\r[$]"

VB.NET: "regex:^" & vbCr & "[$]"

Prefixing a C# string value with the @ character (such as @"regex:{.*@.*}\[.*] ") is a way to specify a literal string - one where (among other things), a backspace is not interpreted as an escape character. This is not needed in VB.NET because backslash is not an escape character there.

Please note the "Lucent CellPipe ADSL modem" case - this modem's shell sends LF CR line endings instead of commonly used CR LF. Due to this, it was necessary to also match \r in addition to $. Also, it is not possible to match either CR or LF using a "string" or "mask" prompt type.

Once you have the Shell object with the proper Prompt specified (and read the welcome message) you can send commands and read responses. To read the complete response, use the ReadAll method:

C#

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

// start the Shell to send commands and read responses 
Shell shell = client.StartShell();

// set the prompt of the remote server's shell first 
shell.Prompt = "servername# ";

// read a welcome message 
string welcome = shell.ReadAll();

// display welcome message 
Console.WriteLine(welcome);

// send the 'df' command 
shell.SendCommand("df");

// read all response, effectively waiting for the command to end 
string response = shell.ReadAll();

// display the output 
Console.WriteLine("Disk usage info:");
Console.WriteLine(response);

// close the shell 
shell.Close();

VB.NET

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

' start the Shell to send commands and read responses 
Dim shell As Shell = client.StartShell()

' set the prompt of the remote server's shell first 
shell.Prompt = "servername# "

' read any welcome message,  
' effectively waiting for the first occurance of the specified prompt 
Dim welcome As String = shell.ReadAll()

' display welcome message 
Console.WriteLine(welcome)

' send the 'df' command 
shell.SendCommand("df")

' read all response, effectively waiting for the command to end 
Dim response As String = shell.ReadAll()

' display the output 
Console.WriteLine("Disk usage info:")
Console.WriteLine(response)

' close the shell 
shell.Close()

Alternatively, the ReadLine method makes it possible to read the response line-by-line:

C#

// create the client, start the shell,  
// set the prompt, read welcome message (as above) 
// ... 

// send the 'df' command 
shell.SendCommand("df");

// read all response line-by-line 
while (true)
{
    // read a single response line 
    string line = shell.ReadLine();

    // a value of null indicates end of response 
    if (line == null)
        break;

    // display the line 
    Console.WriteLine(line);
}

VB.NET

' create the client, start the shell,  
' set the prompt, read welcome message (as above) 
' ... 

' send the 'df' command 
shell.SendCommand("df")

' read all response line-by-line 
While True 
    ' read a single response line 
    Dim line As String = shell.ReadLine()

    ' a value of null indicates end of response 
    If line Is Nothing Then Exit While 

    ' display the line 
    Console.WriteLine(line)
End While 

Finally, character-by-character response retrieval is possible using the ReadChar method:

C#

// create the client, start the shell,  
// set the prompt, read welcome message (as above) 
// ... 

// send the 'df' command 
shell.SendCommand("df");

// read all response char-by-char 
while (true)
{
    // read a single response character 
    char c = shell.ReadChar();

    // a value of Shell.EndOfResponse indicates end of response 
    if (c == Shell.EndOfResponse)
        break;

    // display the character 
    Console.Write(c);
}

VB.NET

' create the client, start the shell,  
' set the prompt, read welcome message (as above) 
' ... 

' send the 'df' command 
shell.SendCommand("df")

' read all response char-by-char 
While True 
    ' read a single response character 
    Dim c As Char = shell.ReadChar()

    ' a value of Shell.EndOfResponse indicates end of response 
    If c = shell.EndOfResponse Then Exit While 

    ' display the character 
    Console.Write(c)
End While 

 

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...