locked
Using TcpClient to do a telnet session RRS feed

  • Question

  • Background: I want to automate a telnet dialog on a non-standard port (i.e. not port 24).

    I tried to establish a simple dialog to a remote computer with TcpClient in C#, VS2005. The documentation provides a nice, compact example (http://msdn2.microsoft.com/en-us/library/system.net.sockets.tcpclient.aspx) which runs, but the output I get is

    Sent: login

    Received: ??↑?? ??#??'

    Actually, no matter what string I send, the Received line is the same. I tried adding another send and receive and still got the same Received line. (To me, it almost looks like a bad baud rate, except I am not using a serial connection!)

    I assume the connection is being established because if I change the port number to a wrong number I get an exception, but on the correct port number it does not complain.

    What am I missing?

     

    Thursday, January 26, 2006 5:14 PM

Answers

  • This seems like an encoding issue (ie. the code is receiving bytes and converting them to a string using the incorrect encoding).  The following is a client and server that should work as you are expecting.  You can vary the encoding to see how that effects the transmitted data.

    Echo and Close server:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Net;
    using System.Net.Sockets;

    namespace echoserver
    {
        class Program
        {
            static void Main(string[] args)
            {

                Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.TypeOfService, 0x03);
                Console.WriteLine("started server...");
                sock.Bind(new IPEndPoint(IPAddress.Any, 5000));
                sock.Listen(4);
                Socket client = sock.Accept();

                byte[] bytes = new byte[1024];
                client.Receive(bytes);
                Console.WriteLine("Received: " + Encoding.ASCII.GetString(bytes));

         client.Send(bytes);
          
         client.Close(); 
         Console.WriteLine("Closed connection to client socket"); 

                sock.Close();
         Console.WriteLine("Closed server socket");
                Console.ReadLine();

            }
        }
    }

    Client to connect to the server (Note: the first parameter on the command line is sent to the server):

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Net;
    using System.Net.Sockets;

    namespace echoserver
    {
        class Program
        {
            static void Main(string[] args)
            {

                TcpClient client = new TcpClient();
         client.Connect(new IPEndPoint(IPAddress.Loopback, 5000));  
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(args[0]);

                NetworkStream stream = client.GetStream();
                stream.Write(data, 0, data.Length);

                Console.WriteLine("Sent: {0}", args[0]);
                data = new Byte[256];
                String responseData = String.Empty;
                int bytes = stream.Read(data, 0, data.Length);
                while (bytes > 0)
                {
      Console.WriteLine("bytes received: " + bytes);
      responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
                    Console.WriteLine("Received: {0}", responseData);
      bytes = 0;
                    bytes = stream.Read(data, 0, data.Length);
                }
                client.Close();

            }
        }
    }

    Tuesday, February 7, 2006 4:47 AM
  • There should be nothing different.  To debug you will want to take a trace when using each approach and compare the data sent
    Monday, February 27, 2006 4:22 AM

All replies

  • This could be an encoding issue, but I suggest first verifying the text you expect to be transmitted is actually being sent/received by using a network tracing tool.  For instructions on how to do this please see http://blogs.msdn.com/dgorti.

     

    Thursday, January 26, 2006 7:10 PM
  • Thanks for the pointer to that network tracing information. I was quite intrigued by the article on System.Net Tracing, so I compiled the tiny test program as indicated and was successful at getting a System.Net.Trace.Log file.

    I then attempted to apply that technique to my original test program (again, which came directly from Microsoft documentation), but I did *not* get any log file, even though I tried all 4 of the source choices listed in the config file.

    There must be some configuration issues I am lacking here...?

     

    Thursday, January 26, 2006 11:04 PM
  • Did you name the config file as
    <app>.exe.config?

     

    Friday, January 27, 2006 3:53 AM
    Moderator
  • Yes
    Friday, February 3, 2006 12:07 AM
  • I got the same problem with this example. I am tying to connect to a Unix Server. I will get the same reply: "?? ?? ??#??'??$"

    I hope someone can give me a hint...

    Monday, February 6, 2006 2:34 PM
  • This seems like an encoding issue (ie. the code is receiving bytes and converting them to a string using the incorrect encoding).  The following is a client and server that should work as you are expecting.  You can vary the encoding to see how that effects the transmitted data.

    Echo and Close server:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Net;
    using System.Net.Sockets;

    namespace echoserver
    {
        class Program
        {
            static void Main(string[] args)
            {

                Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.TypeOfService, 0x03);
                Console.WriteLine("started server...");
                sock.Bind(new IPEndPoint(IPAddress.Any, 5000));
                sock.Listen(4);
                Socket client = sock.Accept();

                byte[] bytes = new byte[1024];
                client.Receive(bytes);
                Console.WriteLine("Received: " + Encoding.ASCII.GetString(bytes));

         client.Send(bytes);
          
         client.Close(); 
         Console.WriteLine("Closed connection to client socket"); 

                sock.Close();
         Console.WriteLine("Closed server socket");
                Console.ReadLine();

            }
        }
    }

    Client to connect to the server (Note: the first parameter on the command line is sent to the server):

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Net;
    using System.Net.Sockets;

    namespace echoserver
    {
        class Program
        {
            static void Main(string[] args)
            {

                TcpClient client = new TcpClient();
         client.Connect(new IPEndPoint(IPAddress.Loopback, 5000));  
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(args[0]);

                NetworkStream stream = client.GetStream();
                stream.Write(data, 0, data.Length);

                Console.WriteLine("Sent: {0}", args[0]);
                data = new Byte[256];
                String responseData = String.Empty;
                int bytes = stream.Read(data, 0, data.Length);
                while (bytes > 0)
                {
      Console.WriteLine("bytes received: " + bytes);
      responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
                    Console.WriteLine("Received: {0}", responseData);
      bytes = 0;
                    bytes = stream.Read(data, 0, data.Length);
                }
                client.Close();

            }
        }
    }

    Tuesday, February 7, 2006 4:47 AM
  • While I appreciate your response, your client is essentially identical to the sample program I mentioned in my initial posting. Your comment about varying the encoding, however, got me looking for the different encoding schemes. After trying all of them listed in System.Text.Encoding, all of them merely produced variations of noise, no better than my original problem statement.

    Note that for the machine I am interested in connecting to, the DOS telnet command connects just fine. So phrasing the problem another way, what is different about telnet vs. using the TcpClient programmatically?

     

    Tuesday, February 7, 2006 11:27 PM
  • There should be nothing different.  To debug you will want to take a trace when using each approach and compare the data sent
    Monday, February 27, 2006 4:22 AM
  • I am having the same problem, where the suggestions to use ENCODING.ASCII fail.  I've resorted to having to convert manually using the crude code below.  I've verified that data is being sent/received successfully using a network sniffer (ethereal).

    I am also having issues with trying to create an event for TCP data arrival.  How do you suggest checking/verifying to see if data has been retrieved?

    Private Function ByteArrayToString(ByVal myIntArray() As Byte) As String
       Dim MyMessage As String = ""
       Dim i As Integer = 0

       Do Until i = UBound(myIntArray) + 1
       If myIntArray(i).ToString >= 32 And myIntArray(i).ToString <= 127 Then
          MyMessage = MyMessage + ChrW(myIntArray(i).ToString)
       End If
       If myIntArray(i).ToString = 10 Then
          MyMessage = MyMessage + vbLf
       End If
       If
    myIntArray(i).ToString = 13 Then
          MyMessage = MyMessage + vbCr
       End If
       i = i + 1
    Loop

    ByteArrayToString = MyMessage
    'MsgBox(MyMessage)

    End
    Function

     

    Wednesday, March 8, 2006 2:47 AM
  • Please start up a new thread for your TCP question.  What encoding does the server use?
    Monday, March 20, 2006 6:10 PM
  • You seem to be connecting fine, but now you have to handle the Telnet protocol.  The first thing the telnet server is going to send you is a bunch of telnet requests to negotiate the terminal settings.  The telnet protocol is defined in RFC 854 (not sure if it has been superseded). 

    On our telnet server (AIX) it sends the following: (NOTE: printed the following looks like '??%??' in the console or a text box):

    char 255 - this is the start of a command

    char 254 - DON'T command

    char 37 - authentication request

    char 255 - another command comming

    char 253 - DO command

    char 24 - Terminal type

    So, the server is asking me to do authentication and that it wants to know what terminal type I want to use for the session.  I should respond with the appropriate responses in the form:

    IAC command option

    according to the telnet spec.  You will have to actually look at the bytes being sent by your server and implement the telnet protocol to talk to the telnet server.

    For the record, it is really disappointing that Microsoft chose not to provide a simple telnet implementation in .NET (like Java does).  So we are forced to do the low level telnet negotiation ourselves.  Come on Microsoft you already have the code in "telnet.exe."

    Tuesday, July 11, 2006 11:45 PM
  • All,

    I was able to script my telnet session to configure a Cisco interface using the following library located in the download in this URL.

    http://www.c-sharpcorner.com/UploadFile/tylerkline/TelnetScripting11282005001158AM/TelnetScripting.aspx?ArticleID=a8e0e439-14df-4d82-82ee-8cb4c110f9a0

    I basically used the WaitFor() and the SendAndWait() public methods to do all of my work.

    Tuesday, July 18, 2006 9:18 PM
  • JeremyH999 and TDAVISJR are both right. I downloaded the code listed by TDAVISJR above and modified it to perform the handshaking required to connect to a QNX telnet server.

    It's necessary to perform the handshake/negotiations first before you'll get back the ubiquitous "login: " response from the server. Each of the commands (eg. starting with IAC, which is byte 255) that is a DO/DON'T usually require a response (WILL/WONT). I'm not sure how much negotiations vary between different telnet hosts, but a good way to check the sort of handshake negotiation that's going on is to use the Microsoft Telnet client (in a command window, just type 'telnet') to connect to your server, and use a Network Packet sniffer to see the communication. I used
    ethereal to do this, and it was quite helpful:http://www.ethereal.com/download.html


    Wednesday, October 3, 2007 7:12 PM
  • here is a more complete minimalistic telnet
    http://www.codeproject.com/KB/IP/MinimalisticTelnet.aspx
    Monday, July 21, 2008 5:29 PM
  • What you are getting here are negotiation codes.  Remember that telnet was first designed to be connected to some form of terminal and it is trying to resolve this with you.  You can find telnet command codes on the internet.  I am attempting the same thing for a Xyplex terminal server but have not gotten past these negotiations.  So anyone who can help me send and receive data I would greatly appreciate it.
    • Proposed as answer by MtEvans Thursday, September 6, 2012 8:56 AM
    Thursday, September 6, 2012 12:57 AM
  • Try my library, or one of the others. Mine is at http://telnetexpect.codeplex.com/ I haven't done many changes recently but it should do the job.

    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, please vote and/or mark the question answered. Available for contract programming.

    Thursday, September 6, 2012 11:16 AM