Go Down

Topic: Get response from telnet server with putty, but not with Arduino telnet client (Read 3 times) previous topic - next topic

vav2sab

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(){
}

SurferTim

I think you need to wait for the telnet server to respond. With no real error checking, this should show the login prompt.
Code: [Select]
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");
  }
}


vav2sab

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

SurferTim

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.

vav2sab

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

Nunov

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 )

vav2sab

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!

pantau

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

vav2sab

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!

Code: [Select]

#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
}

pantau

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:

Code: [Select]

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


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


Regards
Beat

vav2sab

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.

Code: [Select]

#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
}

Go Up