Get response from telnet server with putty, but not with Arduino telnet client

I am stuck with my small project. If I try to connect to a telnet server (non-Arduino) using putty, I receive login prompt, and everything works fine. If I try to use my Arduino Ethernet (see the sample code below), I get the confirmation “connected”, but nothing else appears on the serial monitor.

I tried this with an alternative device also running a telnet server (NETGEAR network router) - again, with putty I get normal text response, with Arduino telnet client I got the following line:

ÿýÿýÿûÿû

Can anybody put me onto the right direction - what I am doing wrong?

#include <SPI.h>
#include <Ethernet.h>

byte mac = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //the actual value matches my Arduino Ethernet
IPAddress ip(192,168,1,177); //the actual value matches my Arduino Ethernet

IPAddress server(1,1,1,1); //the actual value matches my telnet server

EthernetClient client;

void setup() {
Ethernet.begin(mac, ip);
Serial.begin(9600);

delay(1000);
Serial.println(“connecting…”);

if (client.connect(server, 23)) {
Serial.println(“connected”);
while (client.available() > 0) {
char c = client.read();
Serial.print(c);
}
}
else {
Serial.println(“connection failed”);
}
}

void loop(){
}

I think you need to wait for the telnet server to respond. With no real error checking, this should show the login prompt.

void setup() {
  Ethernet.begin(mac, ip);
  Serial.begin(9600);

  delay(1000);
  Serial.println("connecting...");

  if (client.connect(server, 23)) {
    Serial.println("connected");

  // wait for a response. This should also check client.connected() and a timeout.
  while(client.available() == 0) delay(1);

  // get the response
  while (client.available() > 0) {
      char c = client.read();
      Serial.print(c);
    }
  }
  else {
    Serial.println("connection failed");
  }
}

Thank you for the hint. Now, after the string "connected" I am getting a garbage string from my original telnet server similar to the one from the NETGEAR router:

ÿýÿý ÿý#ÿý'

Actually, my original task is to use Arduino Ethernet as a kind of translator between 2 proprietary protocols. One device on some occasions sends raw TCP strings (which Arduino Ethernet receives properly and intact), based on which (using TextFinder library and some intermediate conversions) Arduino Ethernet should send another string to another device running a telnet server. I am stuck with the access to the simple telnet server and do not know, where else to look at (I've googled for it for several hours with no luck).

Those funny characters are the telnet server asking you a few questions. A 255 (0xff) byte is IAC (command start), the next byte is a command, and the third is an option. Some are explained here. http://support.microsoft.com/kb/231866

You need to respond to those first. I should have warned you about that.

Google search "telnet IAC" for more sources of info.

Thanks for the hint - I have figured that too. Software telnet clients (windows or putty) handle those requests by themselves, but Arduino's Ethernet library doesn't seem to be supporting them. Does that mean that my code also should handle those requests, or should I look for an alternative library (if any)?

(Added later) Here's what I have captured - packet-by -packet - when putty (CLIENT) establishes a connection to a telnet host (SERVER). How one can program this negotiation in Arduino? Or maybe somebody knows where to obtain a suitable library?

DESCRIPTION HEX VALUES

CLIENT-- Command: Will Negotiate About Window Size ff fb 1f Command: Will Terminal Speed ff fb 20 Command: Will Terminal Type ff fb 18 Command: Will New Environment Option ff fb 27 Command: Do Echo ff fd 01 Command: Will Suppress Go Ahead ff fb 03 Command: Do Suppress Go Ahead ff fd 03

SERVER-- Command: Do Terminal Type ff fd 18 Command: Do Terminal Speed ff fd 20 Command: Do X Display Location ff fd 23 Command: Do New Environment Option ff fd 27

CLIENT-- Command: Won't X Display Location ff fc 23

SERVER-- Command: Do Negotiate About Window Size ff fd 1f Command: Will Echo ff fb 01 Command: Do Suppress Go Ahead ff fd 03 Command: Will Suppress Go Ahead ff fb 03 Suboption Begin: Terminal Speed ff fa 20 Option data 01 Command: Suboption End ff f0 Suboption Begin: New Environment Option ff fa 27 Option data 01 Command: Suboption End ff f0 Suboption Begin: Terminal Type ff fa 18 Send your Terminal Type 01 Command: Suboption End ff f0

CLIENT-- Suboption Begin: Negotiate About Window Size ff fa 1f Width: 80 00 50 Height: 24 00 18 Command: Suboption End ff f0

CLIENT-- Suboption Begin: Terminal Speed ff fa 20 Option data 00 33 38 34 30 30 2c 33 38 34 30 30 Command: Suboption End ff f0

CLIENT-- Suboption Begin: New Environment Option ff fa 27 Option data 00 Command: Suboption End ff f0

CLIENT-- Suboption Begin: Terminal Type ff fa 18 Here's my Terminal Type 00 Value: XTERM 58 54 45 52 4d Command: Suboption End ff f0

SERVER-- Command: Do Echo ff fd 01 Command: Will Status ff fb 05 Command: Do Remote Flow Control ff fd 21

CLIENT-- Command: Won't Echo ff fc 01

CLIENT-- Command: Don't Status ff fe 05

CLIENT-- Command: Won't Remote Flow Control ff fc 21

SERVER-- Data: login: 6c 6f 67 69 6e 3a 20

Hi, I'm recently new to arduino and i'm using now the ethernet shield. I was able to implement the Chat server sketch but not the Telnet client. I have the same problem described above. Dos anyone found how to solve this?

By the way, is it possible to save in a txt file the info the client sends to the server using telnet? (I found the answer for this one http://www.ehow.com/how_10042564_write-telnet-output-file.html )

Hi there!

Actually, I have solved this problem - sorry for not sharing the solution with the forum members (was travelling - summer, you know). I am going to write a detailed description how to do that, but it is going to take some time. Meanwhile, I can only tell, that the solution was inspired by this nice library:

http://www.codeproject.com/Articles/19071/Quick-tool-A-minimalistic-Telnet-library

Credits to the guy named Tom Janssens!

Take care!

Hi

How would your solution look like? I'm trying to connect to my sound system using telnet on port 23. But the Arduino telnet client does not even connect to it.

It works fine with putty or telnet from same machine.

Regards Beat Graf

Here’s the excerpt of the code. The point is, that Arduino should perform a complete Telnet negotiation routine (terminal programs do it automatically).

Hope it helps!

#include <SPI.h>
#include <Ethernet.h>

EthernetClient host;                                   //  host as Ethernet client

void setup () {                                        //  start connections:
  Serial.begin (9600);                                 //    start console
  byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //    define mac address (optional)
  IPAddress ip (192, 168, 1, 177);                     //    define ip address
  Ethernet.begin (mac, ip);                            //    start Ethernet
}

void inquiry () {                                      //  inquiry host for telnet parameters
  while (host.available () == 0) delay (1);            //    if host does not respond wait for 1 milisecond and loop
  do {                                                 //    loop
    parse ();                                          //      negotiation routine
    delay (200);                                       //      wait for 200 miliseconds
  }
  while (host.available () > 0);                       //    until any character is returned
}

void parse () {                                        //  negotiate telnet parameters with host
  String inpstr;                                       //    input string as string
  int inpint, verbint, optint;                         //    telnet parameters as integers
  while (host.available () > 0) {                      //    if host responds loop:
    inpint = host.read ();                             //      receive returned character
    switch (inpint) {                                  //      evaluate returned character
      case -1:                                         //        if character is nothing
        break;                                         //          break the routine
      case 255:                                        //        if character is 255 (start negotiation)
        verbint = host.read ();                        //          receive negotiation verb character
        if (verbint == - 1) break;                     //          if negotiation verb character is nothing break the routine
        switch (verbint) {                             //          evaluate negotiation verb character
          case 255:                                    //          if negotiation verb character is 255 (start negotiation)
            inpstr += verbint;                         //            add negotiation verb character to input string
            break;                                     //            break the routine
          case 251:                                    //          if negotiation verb character is 251 (will) or
          case 252:                                    //          if negotiation verb character is 252 (wont) or
          case 253:                                    //          if negotiation verb character is 253 (do) or
          case 254:                                    //          if negotiation verb character is 254 (dont)
            optint = host.read();                      //            receive negotiation option character
            if (optint == -1) break;                   //            if negotiation option character is nothing break the routine  
            host.write (255);                          //            send character 255 (start negotiation)
            if (optint == 3)                           //            if negotiation option character is 3 (suppress-go-ahead)
              host.write (verbint == 253 ? 253 : 251); //              send character 253 (do) if negotiation verb character was 253 (do) else send character 251 (will)
            else                                       //            if negotiation option character is not 3 (suppress-go-ahead)
              host.write (verbint == 253 ? 252 : 254); //              send character 252 (wont) if negotiation verb character was 253 (do) else send character 254 (dont)
            host.write (optint);                       //            send negotiation option character
            break;                                     //          break the routine
          default:                                     //        if negotiation verb character is none of the above
            break;                                     //          break the routine
        }
        break;                                         //      break the routine
      default:                                         //    if character is none of the above
        inpstr += char (inpint);                       //      add character to input string
        break;                                         //      break the routine
    }
  }
}

void loop () {                                         //  run your loop routine
}

Thanks for the reply. It does'nt work yet. Just a question: Where do you define the server address and port?

I made a test with following code:

while (!client.connect(server, 23)) {
    Serial.println("connecting...");

The client connected after about 15 tries and another 15s.

Regards Beat

Apologies - my bad. I forgot to include one segment, which performs actual login (I have adapted my original sketch by removing irrelevant parts). Here’s the fixed code - it should work now.

#include <SPI.h>
#include <Ethernet.h>

EthernetClient host;                                   //  host as Ethernet client
String prompt;                                         //  host telnet server prompt as string

void setup () {                                        //  start connections:
  Serial.begin (9600);                                 //    start console
  byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //    define mac address (optional)
  IPAddress ip (192, 168, 1, 177);                     //    define ip address
  Ethernet.begin (mac, ip);                            //    start Ethernet
  loginhost();                                         //    establish connection with host
}

void loginhost () {                                    //  login to host
  IPAddress hostip (192, 168, 1, 103);                 //    specify host ip address
  if (host.connect (hostip, 23)) {                     //    check if host is connected
    inquiry ();                                        //      run inquiry routine
    host.write ("user");                               //      enter user id
    inquiry ();                                        //      run inquiry routine
    host.write ("password");                           //      enter password
    do inquiry ();                                     //      loop inquiry routine
    while (!prompt.endsWith ("# "));                   //      until # prompt is returned
    host.write ("whatever else");                      //      enter another command if needed
    do inquiry ();                                     //      loop inquiry routine
    while (!prompt.endsWith ("some other prompt"));    //      until some other prompt is returned
  }
//  Serial.println ("HOST READY");                       //      confirm successfully established connection
}

void inquiry () {                                      //  inquiry host for telnet parameters
  while (host.available () == 0) delay (1);            //    if host does not respond wait for 1 millisecond and loop
  do {                                                 //    loop
    parse ();                                          //      negotiation routine
    delay (200);                                       //      wait for 200 milliseconds
  }
  while (host.available () > 0);                       //    until any character is returned
}

void parse () {                                        //  negotiate telnet parameters with host
  String inpstr;                                       //    input string as string
  int inpint, verbint, optint;                         //    telnet parameters as integers
  while (host.available () > 0) {                      //    if host responds loop:
    inpint = host.read ();                             //      receive returned character
    switch (inpint) {                                  //      evaluate returned character
      case -1:                                         //        if character is nothing
        break;                                         //          break the routine
      case 255:                                        //        if character is 255 (start negotiation)
        verbint = host.read ();                        //          receive negotiation verb character
        if (verbint == - 1) break;                     //          if negotiation verb character is nothing break the routine
        switch (verbint) {                             //          evaluate negotiation verb character
          case 255:                                    //          if negotiation verb character is 255 (start negotiation)
            inpstr += verbint;                         //            add negotiation verb character to input string
            break;                                     //            break the routine
          case 251:                                    //          if negotiation verb character is 251 (will) or
          case 252:                                    //          if negotiation verb character is 252 (wont) or
          case 253:                                    //          if negotiation verb character is 253 (do) or
          case 254:                                    //          if negotiation verb character is 254 (dont)
            optint = host.read();                      //            receive negotiation option character
            if (optint == -1) break;                   //            if negotiation option character is nothing break the routine  
            host.write (255);                          //            send character 255 (start negotiation)
            if (optint == 3)                           //            if negotiation option character is 3 (suppress-go-ahead)
              host.write (verbint == 253 ? 253 : 251); //              send character 253 (do) if negotiation verb character was 253 (do) else send character 251 (will)
            else                                       //            if negotiation option character is not 3 (suppress-go-ahead)
              host.write (verbint == 253 ? 252 : 254); //              send character 252 (wont) if negotiation verb character was 253 (do) else send character 254 (dont)
            host.write (optint);                       //            send negotiation option character
            break;                                     //          break the routine
          default:                                     //        if negotiation verb character is none of the above
            break;                                     //          break the routine
        }
        break;                                         //      break the routine
      default:                                         //    if character is none of the above
        inpstr += char (inpint);                       //      add character to input string
        break;                                         //      break the routine
    }
  }
}

void loop () {                                         //  run your loop routine
}