Send data over telnet without pressing enter

14,738

Solution 1

You should be able to do this with telnet option negotiation. The protocol defaults to half-duplex mode, and at a minimum for an interactive session, the server should negotiate the suppress go ahead option and echo option.

At the bare minimum you could just spit out ff fb 01 ff fb 03 (will echo, will suppress-go-ahead) at the begining of the session, then reply to any ff fd 01 (do echo) with ff fb 01 (will echo) and reply to any ff fd 03 (do suppress-go-ahead) with ff fb 03 (will suppress-go-ahead).

Edit to add that the linemode negotiation mentioned by Ben Jackson is a better answer. Suppress go-ahead won't be enough for most clients connecting on ports other than 23.

However I think the other problem you're running into is that Java is sending Unicode characters. For example, when you say (char)0xff, Java assumes you're referring to UTF-16 character U+00ff which is ÿ. It's probably sending it over the socket using UTF-8 encoding, so the telnet client sees two bytes: c3 bf which it passes on and displays as ÿ.

What you can do is explicitly tell Java to use ISO-8859-1 encoding. For example, you may have been doing something like this before:

out = new PrintStream(connection.getOutputStream());
out.print((char)0xff);  // sends 0xc3 0xbf
out.print((char)0xfb);  // sends 0xc3 0xbb
out.print((char)0x01);  // sends 0x01
out.flush();

Instead, you can use the OutputStreamWriter to specify the encoding you want:

out = new OutputStreamWriter(connection.getOutputStream(), "ISO-8859-1");
out.write((char)0xff);  // sends 0xff
out.write((char)0xfb);  // sends 0xfb
out.write((char)0x01);  // sends 0x01
out.flush();

Solution 2

There actually is a way for the server to request this: It's called telnet option negotiation. Typically telnet will default to configure the local tty in "raw" mode when you use port 23 and "cooked" (or "line") mode on other ports. Line mode is where you have minimalistic local editing and the data is sent when you hit return.

Once you disable linemode you can separately configure things like local echo.

EDIT: I think a reasonable sequence would be:

255, 253, 34,  /* IAC DO LINEMODE */
255, 250, 34, 1, 0, 255, 240 /* IAC SB LINEMODE MODE 0 IAC SE */
255, 251, 1    /* IAC WILL ECHO */

That enables TELOPT_LINEMODE (34) and then sets the linemode LM_MODE to 0 (which I think is the right way to tell the client not do to any local editing). Finally it says WILL ECHO indicating the server will echo (so the client will not).

The client (if it supports telnet negotiation) will reply with sequences like IAC blah blah or "quoted" sequences like IAC SB ... IAC SE which you can detect and filter out of your input stream.

Solution 3

To configure telnet to send data without pressing enter, you should disable the line mode option. This is done via the mode telnet subcommand:

telnet> mode character

This enables the character at a time mode.

Solution 4

You need to see the documentation (e.g. manual page) for your telnet client.

For example mine (krb5-1.6 telnet implementation on Linux) has a mode character command that turns off local line buffering and sends most characters immediately.

EDIT:

Disabling Local line editing in some other clients, such as PuTTY, has the same result. PuTTY also has a raw connection mode that might be of use.

Please note that if you don't mind implementing some parts of the TELNET protocol on the server, you can also disable Local line editing (the LINEMODE TELNET option) remotely.

If you do not care about interactivity you could also use netcat:

echo -n X | nc host 7777

Unfortunately on many systems (such as mine) netcat uses line-buffered I/O.

Solution 5

My advise is to use netcat for that purposes. It can behave like instant messenger, without pressing enter. searching for netcat tutorial returns tons of videos.

Share:
14,738
Matt
Author by

Matt

SOreadytohelp

Updated on June 09, 2022

Comments

  • Matt
    Matt almost 2 years

    I've recently started messing around with Java sockets and telnet...

    I want the user to be able to connect to the server, just type a letter and have it sent to the server, without pressing enter to send it. I'm sure there's no way for the server to set this up, but maybe telnet has a parameter or something which could allow this?

    Maybe if I got the user to type stty cbreak or stty raw before running telnet, this would work? (UNIX only, I know!)

    If I can get telnet to do this then it saves me having to write a special client just for this feature...

  • Matt
    Matt over 13 years
    Where and how do I send these options?
  • Matt
    Matt over 13 years
    I'm not really understanding where to send these option codes.. I'm trying sending these chars to the client when they connect: out.print((char)0xff); out.print((char)0xfb); out.print((char)0x01); out.print((char)0xff); out.print((char)0xfb); out.print((char)0x03); out.flush(); but that just prints out ÿûÿû^
  • Matt
    Matt over 13 years
    Do I need to go lower level or something?
  • eater
    eater over 13 years
    +1 This looks like the right answer. See my updated answer for how to do it.
  • Matt
    Matt over 13 years
    Using ISO-8859-1 rather than UTF-8 has prevented me from using the extended ASCII chars (128 to 255). I was previously sending them as unicode strings (ie, \u2588 for 219) which obviously no longer work. Instead I tried sending them as characters, so just 219 for example and it just prints them as � characters. Any way to get around this?
  • eater
    eater over 13 years
    I think you could use a PrintStream and an OutputStreamWriter at the same time. Call out = new PrintStream(conn.getOutputStream()); AND rawout = new OutputStreamWriter(conn.getOutputStream(), "ISO-8859-1"); Then you can do rawout.write((char)0xff); to send a single 255 byte, but out.print("whatever \u2588"); for everything else.
  • Asherah
    Asherah over 13 years
    I think it's just that the world is changing and now we've got videos telling us how to use console-based programs.. I can appreciate the humour in it ;-)