Shawn M Moore
and 1 contributors


IO::Socket::Telnet - transparent telnet negotiation for IO::Socket::INET


    use IO::Socket::Telnet;
    my $socket = IO::Socket::Telnet->new(PeerAddr => '');
    while (1) {
        $socket->send(scalar <>);
        defined $socket->recv(my $x, 4096) or die $!;
        print $x;







Negotiation in IO::Socket::Telnet is achieved in two ways. By responding to callbacks and by initiating it yourself.


There are two types of callback: one for the simple IAC <DO|DONT|WILL|WONT> <option> negotiation, and the other for the more complicated IAC SB <stuff> IAC SE.


You can define a simple callback by using


The callback receives two arguments: the socket itself and a human-readable version of the option that is being negotiated. For example, if the server sends "IAC DO ECHO", then the second option will be "DO ECHO". This aims to facilitate the use of regular expressions on the options. If the telnet library doesn't know the name of the particular option being negotiated, it will return its character number instead. Only the first 50 or so characters are assigned meaning in the telnet spec, so if the server sends "IAC WILL chr(63)" then your callback will receive "WILL 63" as its argument.

The callback can return a few different values:

One of: "DO", "DONT", "WILL", "WONT"

These will be interpreted as responding to the other server. They will be packaged into the regular telnet escape codes for you.

0 or 1

These correspond with "DO", "DONT", "WILL", and "WONT" in the obvious way. Zero will return the negation of the input (so WILL generates DONT, WONT generates DO, etc). One returns the affirmative of the input (so WILL generates DO, WONT generates DONT, etc).


A return value of undef will be interpreted by IO::Socket::Telnet as "do the best you can". Generally this is equivalent to returning "DONT" or "WONT" to everything but it may change in the future. This is also the default when no callback it set.

The empty string

The empty string will be interpreted as "do not respond to this negotiation." (Yes, all three canonical false values have different meanings!)

Anything else

Any other return value is sent straight across the socket. This assumes you know what you're doing. Perhaps working around the limitations/ignorance of this module? :)


The complex callback is not specced yet. Right now you receive the raw subnegotiation buffer (if this means nothing to you, then run. RUN!) but there are plans to prettify this input when able. For example, NAWS (negotiate about window size) will probably just hand you the dimensions ($X, $Y) instead of chr($X).chr(0).chr($Y).chr(0).


The four basic option types (DO, DONT, WILL, WONT) each have individual methods (both lowercase and uppercase form). They each take one argument: either the name of the option ('ECHO'), or the character code of the option (chr(1) for ECHO).

There is currently no "easy" way to send complex negotiation. This will be rectified soon. At the very least I want a method that lets you wrap an arbitrary subnegotiation and have it be escaped and packaged correctly.


You must use the $socket->recv(...) method call form. recv($socket, ...) will not invoke the necessary methods. You can use print $socket ... because print currently has no special semantics.

This library does not yet attempt to "remember" negotiations. This means that if you connect with some other client that has the same limitation, you'll likely negotiate infinitely. Thankfully most people aren't terrible like I am. This limitation (endless negotiation, not people being good) will be fixed soon. Honest!


Net::Telnet has a similar purpose, to interact via telnet with someone else. The major difference is that Net::Telnet tries to be Expect to some degree as well. This is fine if that's what you need to do, but the author of IO::Socket::Telnet wants to play NetHack on a remote server, and Net::Telnet doesn't help him very much. I think I have a better negotiation interface as well. :)


Net::Telnet, IO::Socket::INET, IO::Socket, IO::Handle


Shawn M Moore,


Copyright 2007, 2009 Shawn M Moore.
