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

Hello Monks,

Tk and fileevent is a recurring problem. MS Windows makes it more complex. I started using Tkx but gave up. I have code that seems to work fine on Linux, but fails on MS Windows (Activestate Perl 5.8.9). I attach the simplest server and client. Can someone show me how to make a working MS Windows version? The version shown here freezes during processing of the first client data (I think at the end of sub new_connection).

This code works on Linux (at least on my system)

Thank you
taken from http://www.perlmonks.org/?node_id=546243 Updated after the first 3 replies, using: http://code.activestate.com/lists/perl-tk/%3c3A9D513E.CF3B9466@lehigh. +edu%3e/ (this example is about a client, not a server) #!/usr/bin/perl use strict; use warnings; use IO::Socket; use Tk; $| = 1; $SIG{PIPE} = 'IGNORE'; my $listen = IO::Socket::INET->new( Proto => 'tcp', LocalPort => 7777, Listen => 1, Reuse => 1, ) or die "Can't create listen socket : $!\n"; my $mw = MainWindow->new(); my $text = $mw->Scrolled( 'Text', )->pack(); my ($sel); if ( $^O eq 'MSWin32' ) { $mw->repeat( 50 => [ \&new_connection, $listen ] ); } else { $mw->fileevent( $listen, 'readable' => [ \&new_connection, $listen + ] ); } Tk::MainLoop; sub new_connection { my ($listen) = shift; my ($sel); my $client = $listen->accept() or warn "Can't accept connection"; $client->autoflush(1); if ( $^O eq 'MSWin32' ) { use IO::Select; $sel = IO::Select->new; $sel->add($listen); #<<===== $sel problem?? $mw->repeat( 50 => [ \&handle_connection, $client, $sel ] ); } else { $mw->fileevent( $client, 'readable' => [ \&handle_connection, $client, $sel ] ); } $text->insert( 'end', "Connected\t" ); $text->see('end'); } sub handle_connection { my ( $client, $sel ) = shift; if ( $^O eq 'MSWin32' ) { my (@ready) = $sel->can_read(0); return if $#ready == -1; $client = $ready[0]; } my $message = <$client>; if ( defined $message and $message !~ /^quit/ ) { $message =~ s/[\r\n]+$//; $text->insert( 'end', "Got message [$message]\t" ); $text->see('end'); } else { $text->insert( 'end', "Connection Closed\n" ); $text->see('end'); $client->close(); } }
A simple client
#!/usr/bin/perl use IO::Socket; my $machine_addr = 'localhost'; $sock = new IO::Socket::INET(PeerAddr=>$machine_addr, PeerPort=>7777, Proto=>'tcp', ); die "Could not connect: $!" unless $sock; foreach my $count(1..100){ print $sock "$count\n"; print "$count"; } close ($sock);

Replies are listed 'Best First'.
Re: tk, fileevent, and MS Windows
by zentara (Cardinal) on Mar 21, 2011 at 15:18 UTC
      I'm clearly not the only one struggling.
Re: tk, fileevent, and MS Windows
by Equidor (Sexton) on Mar 21, 2011 at 15:39 UTC

    Just a quick glance, one thing stands out: in your $mw->fileevent declaration the compiler is thinking that you are declaring the entire sub new_connection(). What you want to do instead is pass a reference to the sub:

    $mw->fileevent( $listen, 'readable', [ \&new_connection, $listen ] );

    I'm --fairly-- sure that what I'm doing with the anonymous list brackets for the callback function is what works in Tk for passing parameters to the sub. I've done it before but my scripts doing that are elsewhere on a different machine.

    Cheers!

      I'm not sure I fully understand the consequences, but adapted the code.
Re: tk, fileevent, and MS Windows
by sierpinski (Chaplain) on Mar 21, 2011 at 13:46 UTC

    I don't currently have the ability to try to run this code, but the first thing that pops out when you're talking about Linux vs Windows is the newline characters. I see you are using \r\n, which should be correct for Windows, but that makes me wonder whether or not you made any changes for the Linux version to work? I don't know offhand what \r does in a unix environment.

    What troubleshooting have you done in that arena? Do you have any debug information? Also, try removing the \n from the print $sock statement in your client. I've had issues where my socket would only send the first line (which was blank in my case) and then exit.

    Just some thoughts... when I get to my workstation I'll try to run the code to see how it works.