#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2004
    Posts
    4
    Rep Power
    0

    Simple Telnet Client


    hiya everyone... ummm i am wondering if someone can direct me to a tutorial on making a telnetclient that is well... able to do the minimum that a telnet client should do...ie send commands to the server (via some text input) and receive data from the server... and whatever else it needs to do...sooo if anyone can direct me to such a place i would be very grateful :D I am using MSVC6 btw
  2. #2
  3. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    http://www.faqs.org/rfcs/rfc854.html

    if you already are familiar with the sockets API that is all you really need.
  4. #3
  5. Lord of Dorkness
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2004
    Location
    Central New York. Texan via Arizona, out of his element!
    Posts
    8,524
    Rep Power
    3314
    Infamous, I just read your newest link. As soon as I get a corporation and a coffer, I'm gonna hire you and fatten it :D .
    Functionality rules and clarity matters; if you can work a little elegance in there, you're stylin'.
    If you can't spell "u", "ur", and "ne1", why would I hire you? 300 baud modem? Forget I mentioned it.
    DaWei on Pointers Politically Incorrect.
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,183
    Rep Power
    2222
    Besides RFC 854, "TELNET PROTOCOL SPECIFICATION" (link provided by infamous), I would also recommend RFC 1143, "The Q Method of Implementing TELNET Option Negotiation", at http://www.faqs.org/rfcs/rfc1143.html. RFC 1143 describes an approach to simplifying the negotiation process that I found quite useful. Basically, respond to every DO and WILL message from the server with a WONT and DONT, thus turning off all the special stuff. But don't make the mistake I did and respond to a WONT from the server; we kept getting into literally endless arguments agreeing with each other: "WONT" "DONT" "WONT" "DONT" ... ad infinitum.

    I had started my sockets programming projects with a telnet client and so had gone through this before. I wrote my first utitlity, MiM ("Man in the Middle"), to capture the traffic between a telnet client and server in order to see exactly what negotiations were going on. It would be good experience for you to write your own, but I'll attach it to this message anyway. MiM.ZIP also contains my utility, MUNGE, which "de-mungs" the capture file, turning the binary negotiation commands into human-readable numeric codes. You use MiM by starting it with the server address, then you start up a telnet client and point it to MiM. Since it was my first real project, its shutdown is anything but graceful, but at least it will capture the negotiation during start-up. BTW, both MiM and MUNGE were developed under VC++6, which is what you're using. Also, some of the notes in the history file relate to my wanting to transition over to MinGW gcc; I forget how far I'd gotten, but I'm pretty sure that what you have there should build.

    NOTE: I seem to be have difficulties uploading MiM. I'll try later at home.

    Also, in your client you will need to recognize when a command is coming in and filter it out of the actual data stream. For that, you will definitely need to use RFC 854. I seem to recall that I ended up using a finite-state-machine approach and feeding one character at a time into the machine.

    For the moment, I've forgotten where I archived my telnet test program. There are other telnet clients up on the Web with source code that you should be able to find via Google. I mention them in the spirit of learning by reading somebody else's code.
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2004
    Posts
    4
    Rep Power
    0
    hmmmm i'll give this a shot... basically i just need to make something to connect to a telnet server, receive what the server sends and then by clicking buttons send info to the server... so yeah... i just need a bear minimum client.... so i'll see what i can do
  10. #6
  11. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,183
    Rep Power
    2222
    Originally Posted by Utimagus
    hmmmm i'll give this a shot... basically i just need to make something to connect to a telnet server, receive what the server sends and then by clicking buttons send info to the server... so yeah... i just need a bear minimum client.... so i'll see what i can do
    I just re-located an output file from MUNGE. The numbers after the back-slashes are binary data given in decimal. Also note at the end that the server was sending ANSI terminal commands. This was just a regular telnet session using the client and server and came with the systems.

    The idea here being that your client would need to be able to detect and handle the commands and to strip them out of the text data that it would display.
    Code:
    Opened file: redhat.dat
    Client: \255 \253 \3    // DO suppress go ahead
            \255 \251 \24   // WILL terminal type
            \255 \251 \31   // WILL window size
            \255 \251 \32   // WILL terminal speed
            \255 \251 \33   // WILL remote flow control
            \255 \251 \34   // WILL linemode
            \255 \251 \39   // WILL ????
            \255 \253 \5    // DO status
    Server: \255 \253 \24   // DO terminal type
            \255 \253 \32   // DO terminal speed
            \255 \253 \35   // DO ????
            \255 \253 \39   // DO ????
    Client: \255 \252 \35   // WONT ????
    Server: \255 \251 \3    // WILL suppress go ahead
            \255 \253 \31   // DO window size
            \255 \253 \33   // DO remote flow control
            \255 \254 \34   // DONT linemode
            \255 \251 \5    // WILL status
    Client: \255 \250       // start subnegotiation
                \31 \0 P\0 \25  
            \255 \240       // end subnegotiation
    Server: \255 \250       // start subnegotiation
               \32 \1 
            \255 \240       // end subnegotiation 
            \255 \250       // start subnegotiation
                \39 \1 
            \255 \240       // end subnegotiation 
            \255 \250       // start subnegotiation
                \24 \1 
            \255 \240       // end subnegotiation 
    Client: \255 \250       // start subnegotiation
                \0 38400,38400 
            \255 \240       // end subnegotiation
            \255 \250       // start subnegotiation
                \39 \0 
            \255 \240       // end subnegotiation
            \255 \250       // start subnegotiation
                \24 \0 LINU
    Client: X\255 \240      // end subnegotiation
    Server: \255 \253 \1    // DO echo
    Client: \255 \252 \1    // WONT echo 
    Server: \255 \251 \1    // WILL echo
            \13
    Red Hat Linux release 7.0 
    Server: (Guinness)\13 
    Kernel 2.2.16-22 on
    Server:  an i586\13 
    
    Client: \255 \253 \1    // DO echo
    Server: login: 
    Client: w
    Server: w
    Client: i
    Server: i
    Client: s
    Server: s
    Client: e
    Server: e
    Client: \13 \0 
    Server: \13 
    
    Server: Password: 
    Client: z
    Client: 1
    Client: 2
    Client: 3
    Client: 4
    Client: \13 \0 
    Server: \13 
    
    Server: Last login: Fri Jan 18 07:59:09
    Server:  from pc14402\13 
    
    Server: [wise@pc10593 wise]$ 
    Client: l
    Server: l
    Client: s
    Server: s
    Client: \13 \0 
    Server: \13 
    
    Server: \27 [00m\27 [01;34mbin\27 [00m  \27 [01;34m
    Server: nsmail\27 [00m  \27 [01;34mprojects\27 [
    Server: 00m\13 
    \27 [m[wise@pc10593 wise]$ 
    Client: w
    Server: w
    Client: h
    Server: h
    Client: o
    Server: o
    Client: \13 \0 
    Server: \13 
    
    Server: wise     tty2     Jan 18 07:48\13 
    Server: 
    wise     pts/0    Jan 18 08:00
    Server: \13 
    [wise@pc10593 wise]$ 
    Client: e
    Server: e
    Client: x
    Server: x
    Client: i
    Server: i
    Client: t
    Server: t
    Client: \13 \0 
    Server: \13 
    
    Server: logout\13 
    \27 [H\27 [J
    Server:
  12. #7
  13. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2004
    Posts
    4
    Rep Power
    0
    hmmm i seem to be having probs even starting... is there a really simply telnet client out there...the ones i've found are usually completed software packages that are pretty confusing... so does anyone know of a sample program with source that is just like a console program that is torn down to the bear minimum?
  14. #8
  15. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    Originally Posted by DaWei_M
    Infamous, I just read your newest link. As soon as I get a corporation and a coffer, I'm gonna hire you and fatten it :D .
    hmm... i hope your not also plotting an "accident" where a pallet of grape jelly jars fall and crush me to death, b/c i was plotting to outlast you and take over the company once you've built it up nicely. :D

    Originally Posted by Utimagus
    hmmm i seem to be having probs even starting... is there a really simply telnet client out there...the ones i've found are usually completed software packages that are pretty confusing... so does anyone know of a sample program with source that is just like a console program that is torn down to the bear minimum?
    did u not read a thing that dwise just posted??!!
  16. #9
  17. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2004
    Posts
    4
    Rep Power
    0
    i did, i don't know any of the syntax to get started at all... i've never done anything with protocols nor communications
  18. #10
  19. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,183
    Rep Power
    2222

    A design strategy


    Originally Posted by Utimagus
    i did, i don't know any of the syntax to get started at all... i've never done anything with protocols nor communications
    The syntax is specified in the RFCs. For that reason, you will always need to have copies to refer to -- I get my copies by just saving the web page when I look one up on the Web. I would recommend that you also save off the RFC index page that lists them all. And always be sure to check to check whether that RFC has been rendered obsolete by a later one (this is annotated on the index page).

    As for starting the project, I'm reminded of what we were taught in school, when "structured programming" was the big buzzword. We were taught to take the approach of "divide and conquer". You are face with a big task, so start breaking it down into smaller tasks, and then each of those tasks into even smaller ones, until you have lots of little tasks, each of which is easy to do.

    Hopefully this is all old stuff to you, but I've learned not to take such things for granted.

    Figure out what your telnet client will do. Break that up into functional parts. Then implement each functional part (with an eye on how they will all tie together, of course).

    Your client will need to display incoming text on the screen. So write the code to do that. I would recommend having one function that writes to the screen and then it gets called for everywhere in the program that needs it, as opposed to sprinkling printf's throughout the code. That way, if there's something you need to change about how you write to the screen, you only need to change it in one place. Also, the rest of your program doesn't need to know how it's done.

    A separate function is your need to input text from the keyboard and figuring whether to echo it back out or not. I would make this one function also that will eventually need to determine whether you are typing in text to be sent to the server or else a local command and it will need to handle the input text accordingly.

    After you have those, you need to be able to handle sockets. You can start with an echo server instead of a telnet server (Donahoo & Calvert have some at their site; link given on my resources page) and write and test your ability to process the command-line parameters (IP address or host name, port) and use them to connect to a server and pass messages back and forth. You would probably want to break this down into smaller tasks and tackle one at a time. Eg, you could rewrite the echo server to also echo out onto its screen what it had received from the client.

    I would recommend during this point of the development that the messages received from the server be sent to a function for processing. Right now, all that function will do is pass the text directly to the display function. But when you get to the stage of connecting to a telnet server, you will want this function to detect commands coming in, process them, and send NON-command text straight to the display function (thus filtering the commands out of the data stream).

    Read the telnet specification, RFC 854, because that is the key to the whole thing. See what the format of a command is (for one thing, it starts with IAC, 255). I used a state machine (basically a glorified switch statement). My state machine started off reading text, but when it detected IAC, it went to the state for handling that. In that state, it identified the command as given in the next byte and so knows how many more bytes would be part of the command. After it had read the last byte, it processed that command (most were simply ignored) and then went back to processing text. An example of processing a command would be to respond to a DO command with a WONT; read the RFC and you will understand what those are.

    When you implement your state machine or however you want to do it, you can test it off-line. Have a data file of test message-data (or hard-code it into your test program) and pass that data to the function and have it print out the results. After you are satisfied that it works, then put it into your program and try going live with it.

    And that, off the top of head, is my first approach to how I would do this project.
    Last edited by dwise1_aol; July 13th, 2004 at 04:13 PM.

IMN logo majestic logo threadwatch logo seochat tools logo