Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Telnet Client/Server: What am I doing wrong?

by PM_Visitor (Initiate)
on Dec 15, 2012 at 02:24 UTC ( [id://1008923]=perlquestion: print w/replies, xml ) Need Help??

PM_Visitor has asked for the wisdom of the Perl Monks concerning the following question:

Dear Perl Monks:
I am trying to write a GUI tool in Perl/Tk. It's purpose is to drive equipment at work, which is a
digital cross connect system. I have have almost everything debugged and working in a simulation mode.
What I haven't yet figured out is the network communication part.

When I use the stock Microsoft Telnet program, the server responds properly, the response is immediate.
For both a "!" response to a CR, and for a command sent. Works properly.

When I use Perl's socket functions in my Client (use Net::Telnet on the Client) and (use Socket) on the server,
I have to send another "!" for the Client to show the data on the screen.

I figure that since the stock Telnet program works properly, it's not the server (use Socket).

My Client's local console gets updated the same time as the Tk text window.
(after ! is sent after a command is sent to the server).

In my program the Perk/Tk GUI... the link partially works. (1 for 1 with a ! sent),
but when I send a command an extra CR/! is needed for data to appear on the client side
(on both console and Tk windows). (Yes, I repeated myself, sorry... and I think I repeat below as well).
-------------------------------------------------------------------------------
Here are code samples. Client side, and this works... gets an immediate response. (which is a "!")

$t->print("!"); my $data = $t->get(); print STDOUT "$data\n"; WriteToScreen($data); return;

-------------------------------------------------------------------------------
Client Side, and this does not work... I have to enter another ! (the above) to get a response.

print STDOUT "Get_CMap() Live Mode\n"; select($t); $t->print($CMap_cmd); $t->flush(); # this flushes the ouput buffer, but it is $|=1 anyway. $newCMapData = $t->get(); print STDOUT "$newCMapData\n"; WriteToScreen($newCMapData);
-------------------------------------------------------------------------------
My program's write sub: (the scroll bar works ok, everything else works ok).
sub WriteToScreen { my ($msg) = @_; $screen->insert("1.0", $msg); $numlines = ($screen->index("end")-1); $screen->configure(-state => "normal"); if ($screen->index("end-1c") != "1.0") { $screen->insert_end("\n"); } $screen->insert_end($msg); $screen->see("1.0"); $screen->configure(-state => "disabled"); $screen->yview("end"); }
-------------------------------------------------------------------------------
Data being sent by the server: (works with stock telnet, does not work with my program (as above):

$cm1 = "M 11:24:49 25,00 7 UTL QRY CMAP 064 TODC---- TYPE DC102 4 LN M +SG:\r\n 04124 20003 19317 19318 00000 19320 19324 19315\r\n 19323 19314 19316 19319 00000 19601 00000 20103\r\n 19604 07301 07302 07303 00403 07304 19407 19410 COMPL\r\n";

-------------------------------------------------------------------------------
This is the key routine in the server... sends the above data.

if ($cmd =~ m/cmap 111/ig) { select (NS); $|= 1; select (NS); print NS "$cm1"; print NS "\n"; print STDOUT "$cm1"; }

This is the portion of the server that sends the ! in response to a !:

if ((length($ll) < 3) && ($ll !~ /!/g)) { print NS "!"; print STDOUT "3!\r\n"; next; }
This is my first post here. Sorry if it is not what is wanted. I don't get what I'm doing wrong. At the risk of repeating myself... When I send a ! I get a ! right back (my choice of a communication indicator). No delay, nothing further needed. When I send a command (in this case cmap 111), the data does not come back to the client until another ! is sent.

Any ideas on what might be causing this? I've got the buffers set hot ($|=1;) and I have a good pipe between the two endpoints (at this time it is just thru my local computer's stack... two different ports). The server script uses the Socket code. The Client uses Telnet code. Should I go to Socket code on the Client...? Are there incompatibilities between the two systems? I assume since Telnet works ok, the server code is ok. I realize that programming is not a spectator sport, and that I'm not really a programmer. But I'm trying. Have tried, and have worked this one over a lot before posting here. Thanks in advance for your help.

Replies are listed 'Best First'.
Re: Telnet Client/Server: What am I doing wrong?
by zentara (Archbishop) on Dec 15, 2012 at 10:52 UTC
    You have explained your problem, but without running examples, it is hard to say what is wrong. Try this Tk socket client, and see how it works.
    #!/usr/bin/perl use warnings; use strict; use Tk; use IO::Socket; require Tk::ROText; # create the socket my $host = shift || 'localhost'; my $port = 7070; my $socket = IO::Socket::INET->new( PeerAddr => $host, PeerPort => $port, Proto => 'tcp', ); defined $socket or die "ERROR: Can't connect to port $port on $host: $ +!\n"; print STDERR "Connected to server ...\n"; my $mw = new MainWindow; my $log = $mw->Scrolled(qw/ROText -scrollbars ose/)->pack; my $txt = $mw->Entry()->pack(qw/-fill x -pady 5/); $mw ->bind('<Any-Enter>' => sub { $txt->Tk::focus }); $txt->bind('<Return>' => [\&broadcast, $socket]); $mw ->fileevent($socket, readable => sub { my $line = <$socket>; unless (defined $line) { $mw->fileevent($socket => readable => ''); return; } $log->insert(end => $line); }); MainLoop; sub broadcast { my ($ent, $sock) = @_; my $text = $ent->get; $ent->delete(qw/0 end/); print $sock $text, "\n"; }

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh

      Thank you, very much.

      Not knowing any better, I started with the Tkx version of Tk. So, without rewriting your example, it's not going to run.
      I guess I can install the Tk package (new to that also, don't know if installing Tk will break Tkx (and what I've scruffed together so far--2 weeks of learning :) )).

      I would upload the working program, but it's now at about 1500 lines... so should I zip the program up and post it? It's probably not what an experienced Perl programmer would create.

      I have started reading 'Network Programming with Perl, Lincoln Stein'. Perhaps that will enable me to resolve my obtuseness.

      I'm not giving up! The first version was in HTML5, CSS3, and Javascript. The problem there was that WebSockets (and Flash) have a handshaking overhead before they will open a plain socket. Security reasons it looks like. (so poof, there went 4 days of work... should have nailed down the comm part first).

      So anyway, thanks for the response.... will installing Tk break Tkx?

        will installing Tk break Tkx?

        No, they are completely different modules, although Tkx does closely mimic Tk. You can install them side by side, no problem.


        I'm not really a human, but I play one on earth.
        Old Perl Programmer Haiku ................... flash japh

        I would upload the working program, but it's now at about 1500 lines... so should I zip the program up and post it?
        No. It is inconsiderate to expect unpaid volunteers to read and understand 1500 lines of your code.

        Instead, you should prepare and post here a short self-contained correct (compilable) example that demonstrates the problem you are trying to solve.

Re: Telnet Client/Server: What am I doing wrong?
by RichardK (Parson) on Dec 15, 2012 at 17:45 UTC
    print STDOUT "Get_CMap() Live Mode\n"; select($t); $t->print($CMap_cmd); $t->flush(); # this flushes the ouput buffer, but it is $|=1 anyway. $newCMapData = $t->get(); print STDOUT "$newCMapData\n"; WriteToScreen($newCMapData);

    What is the select in this code for? i.e. what do you think it's doing ?

    and why do you need the flush?

      Hi RichardK....
      To answer as best I can... The selection of the output file handle 'select($t)' is not needed---now I realize that it is not necessary since '$t->print()' directs output to the file handle (which is the socket). The $t->flush() is an attempt to ensure that the command is sent--I learned this also is not necessary.

      Then I get the response (which is buffered and not displayed until another carriage return is sent. Which is the key problem that I'm stuck on).

      I can get the link to work by calling my 'SendCR()' Client sub (which merely sends a a "!\n"). So that's my work around, until I can fathom the process. I've been reading and working examples. The work around will do for the rest of the program development...but it's not technically the right answer. (sigh). Thanks for your response.

      I don't want anyone to debug my program for me... the previous post asked for working examples... it's difficult to cut out brief parts... sorry that was not enough to relay the problem. It will shine when it shines. The learning curve is the difficult to cross at times. Thanks again, take care.

        the previous post asked for working examples... it's difficult to cut out brief parts

        Though it may be difficult, it's a good training exercise for you in learning Perl. The act of creating a small cut-down program should help you focus on and better understand the problem; you may even find you're able to identify the problem and fix it yourself.

        BTW, instead of your global NS file handle and the:

        select (NS); $|= 1; select (NS);
        claptrap, you should use a lexical file handle ($ns say) and then simply:
        use IO::Handle; # ... $ns->autoflush();

        For Perl 5.14+ you don't even need use IO::Handle because:

        Before Perl 5.14, lexical filehandles were objects of the IO::Handle class, but you had to load IO::Handle explicitly before you could call methods on them. As of Perl 5.14, lexical filehandles are instances of IO::File and Perl loads IO::File for you.

        With recent Perls (5.8+), there's no need anymore to confusingly change the (global) default destination for print statements via the old evil one-argument form of select -- for more details, see Perl Best Practices, chapter 10 (I/O) and Perl tip: Buffering and IO::Handle by TheDamian.

        Suggest you further read Suffering from Buffering by MJD.

        You said you were using Net::Telnet for the client, but I can't see a method called SendCR in the pod Net::Telnet. So what are you using, and have you read the docs? :)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1008923]
Approved by McDarren
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (4)
As of 2024-04-19 22:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found