Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

TK MainLoop and Sockets

by Anonymous Monk
on May 03, 2004 at 03:47 UTC ( [id://349908]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks, I have built a TK GUI Server that looks fine. My problem is that I have a client program that seeks info on the web and then sends a message to the GUI server. I created a socket on the server and it listens with the 'accept' method. The 'accept' method won't turn the process loose to allow me to rebuild parts of the GUI diplay after receiving data from the client. It just sits and continues to listen. I understand that the MainLoop is looking for an event to handle but fileevent goes into an endless loop when I try to use that and anything else just locks up after the first client connection. How can I make the client connecting to the server and the 'accept' method get handled as an event controlled by the MainLoop?? Thanks soooo much.. the_wildman

Replies are listed 'Best First'.
Re: TK MainLoop and Sockets
by strat (Canon) on May 03, 2004 at 07:49 UTC

    Maybe POE might be interesting for you, e.g.

    But I haven't tried to use it in combination with Tk, so this message is just a guess...

    Best regards,
    perl -e "s>>*F>e=>y)\*martinF)stronat)=>print,print v8.8.8.32.11.32"

Re: TK MainLoop and Sockets
by DigitalKitty (Parson) on May 03, 2004 at 06:19 UTC
    Hi the_wildman.

    This sounds like an interesting project. Could you post the code you have written so far?

    Thanks,
    -Katie.
      Katie, I'll get back to you with the code. Because of all the problems I've had reading from sockets within a GUI, it looks pretty ugly right now. the_wildman
Re: TK MainLoop and Sockets
by zentara (Archbishop) on May 03, 2004 at 19:28 UTC
    The 'accept' method won't turn the process loose to allow me to rebuild parts of the GUI diplay after receiving data from the client. It just sits and continues to listen. I understand that the MainLoop is looking for an event to handle but fileevent goes into an endless loop when I try to use that and anything else just locks up after the first client connection.

    Without seeing your code, it sounds like the socket is blocking. Tk has 2 ways of dealing with it, Tk::Fileevent and Tk::After. You have to let Tk's methods handle the socket reading, so it won't block the "event loop".

    Here is an example that was posted awhile back:

    #!/usr/bin/perl use warnings; use strict; use Tk; use Symbol qw(gensym); use IO::Socket; $ENV{HOME} = "/" unless $ENV{HOME}; print( "Listening on localhost port 31415. Telnet to it and try\n", "entering something. In an ideal world, it should echo back.\n +" ); my $acceptor = IO::Socket::INET->new ( LocalAddr => '127.0.0.1', LocalPort => 31415, Listen => 5, Reuse => 'yes', ); my $client = $acceptor->accept(); die "Could not accept a client: $!" unless defined $client; print "Client connection accepted.\n"; # Turn off buffering. select((select($client), $| = 1)[0]); # Send a welcome message. print $client "Hello!\x0d\x0a"; print "Setting callback for $client.\n"; my $main_window = Tk::MainWindow->new(); $main_window->fileevent( $client, 'readable', [ \&read_client ] ); print "Callback set.\n"; Tk::MainLoop(); exit 0; sub read_client { print "Client callback has been invoked.\n"; my $line = <$client>; exit unless defined $line; print $client $line; }

    I'm not really a human, but I play one on earth. flash japh
      zentara, I really appreciate your help. This script you have provided is the same as I am using, for the most part. I have the same problem here. The 'fileevent' executes on the event, but only once. I need it to execute on the accept(), move to the callback and then set up for another accept(). I didn't use the telnet part. I send from another socket. That info gets there, once. As the info changes, I want to resend to this server and update the GUI. Or at least that's what I'm trying to accomplish. wildman
Re: TK MainLoop and Sockets
by zentara (Archbishop) on May 04, 2004 at 20:01 UTC
    Well you are not showing your code, so all we can do is guess and show code that works. I tend to go in phases with sockets...I get all into it, then it all fades out of my active memory, and it gets hazy. Anyways, the last time I dove in to Tk and sockets, I came up with this as a working example with fork. This is the set of snippets I refer to as a basic starting point for forking Tk sockets with Select. So run them, and see how to make your scripts work the same. They are sort of a "minimal proof of concept".
    #######the server############################## #!/usr/bin/perl -w use strict; use IO::Select; use IO::Socket; $| = 1; # create the socket my $host = shift || 'localhost'; my $port = 12345; my $socket = IO::Socket::INET->new( LocalPort => $port, LocalAddr => $host, Listen => 5, Proto => 'tcp', Reuse => 1, ); defined $socket or die "ERROR: Can't create socket: $!\n"; print STDERR "Socket open ... listening for incoming calls ..\n"; my $select = IO::Select->new($socket); my %socks; while (1) { foreach my $fh ($select->can_read) { if ($fh == $socket) { # new connection my $new = $socket->accept; $select->add($new); $socks{$new}{FH} = $new; print STDERR "Received new connection ($new) ..\n"; } else { my $data = <$fh>; if (defined $data) { $data =~ tr/\r\n//d; foreach my $handle (keys %socks) { print {$socks{$handle}{FH}} "$handle $data\n"; } } else { print "BYE $fh.\n"; $select->remove($fh); delete $socks{$fh}; $fh->close; } } } }

    ########the client###################### <code> #!/usr/bin/perl use warnings; use strict; use Tk; use IO::Select; use IO::Socket; require Tk::ROText; # create the socket my $host = shift || 'localhost'; my $port = 12345; 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. flash japh

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (2)
As of 2024-04-20 10:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found