http://qs321.pair.com?node_id=278704

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

I have a pretty large app (WinXP) that uses IO::Socket::SSL to send XML commands to a hardware device. I built a front-end to it in Tk, but when I press the connect button, the GUI freezes until the socket is opened, and all of the reply has been recieved from the device and the socket is closed. On subsequent connects, it takes less time. I am guessing that the problem is that the socket is blocking? So, I tried using a non-blocking example out of the Liddie Mastering Tk book...but I couldn't get it to work with SSL (arrgh) so I thought I would give POE a try. It works, but I have one really petty performance issue that I was wondering if anyone knew how to overcome... that being is their any way to speed this up or at least let me move the window while it is running? using ASPerl(5.80) POE(0.25) Tk(8.024) Here is a skeleton example:
use strict; use warnings; use Tk; use POE; use POE::Component::Client::HTTP::SSL; $|++; POE::Session->create( inline_states=> { _start => \&connect, send => \&send, get_input => \&get_input, listen => \&listen, }, ); $poe_kernel->run(); sub connect { my ($kernel,$heap,$session) = @_[KERNEL,HEAP,SESSION]; my $buf; my $mw = $poe_main_window; $heap->{txt} = $mw->Scrolled('Text',-width, 50,-height, 20,-scroll +bars, 'osoe')->pack(-fill,'both',-expand, 1); $mw->Button(-text, 'Run', -command, $session->postback("send"))->p +ack; $kernel->yield("listen"); } sub send { my ($kernel,$session,$heap) = @_[KERNEL,SESSION,HEAP]; tie( *SSL, "POE::Component::Client::HTTP::SSL", "www.openssl.org", + "443") or warn "can't open socket\n"; if( \*SSL ){ $heap->{sock} = \*SSL; $heap->{sock}->print("GET http://index.htm \r\n"); $kernel->yield('listen'); } } sub get_input { my ($kernel,$heap) = @_[KERNEL,HEAP]; $kernel->yield('listen'); } sub listen { my ($kernel,$session,$heap) = @_[KERNEL,SESSION,HEAP]; if(defined $heap->{sock}){ my $buf; $heap->{sock}->blocking(0); $heap->{sock}->read($buf, 1024); $heap->{txt}->insert('end',$buf); } $kernel->yield('get_input'); }


Here is blocking example to show the difference:
use Net::SSLeay::Handle; use Tk; my $mw = tkinit; my $txt = $mw->Scrolled('Text', -width,50,-height,20, -scrollbars, 'os +oe')->pack(-fill,'both',-expand,1); $mw->Button(-text,'Run',-command, \&send)->pack; MainLoop; sub send { tie (*SSL, "Net::SSLeay::Handle", "www.openssl.org", "443") or die + "error in tie\n"; if(\*SSL){ print SSL "GET http://index.html \r\n"; } while(my $buf = <SSL>){ $txt->insert('end',$buf); } }
Thanks in advance,
JamesNC

update (broquaint): added missing line of code

Replies are listed 'Best First'.
Re: Tk POE SSL Win32 help
by JamesNC (Chaplain) on Jul 29, 2003 at 13:25 UTC
    FYI: you need to add: my $buf; to line 52 ( I was tired when I posted and I can't edit the node because ) to rid the warning...
Re: Tk POE SSL Win32 help
by paulbort (Hermit) on Jul 29, 2003 at 20:09 UTC
    I suspect the problem is somewhere in the layer between your Perl code and Win32. This usually happens when the program calls for a system service in such a way that either (a) the system won't send it messages until that call comes back; or (b) the program can't catch messages because it's busy waiting for the API call to return. The solution is to use either a separate process (Then you have to figure out how to pass the connection around) or a separate thread (not recommended for production, IIRC.) I'd try the thread first. If you wanted to be clever, the thread could put up a progress dialog separate from the main window...

    --
    Spring: Forces, Coiled Again!
      Thank you for your response, however Tk is not thread safe, and really, POE is handling that chore pretty well. If you notice the get_input session may not seem to do anything and it doesn't as it is shown, but if you put some work in there ( like a counter, or open another socket ) you would see that POE is working as advertise and Rocco's SSL client is not blocking. SSL is just slow to fire up for some reason, but after it makes the first connection, things run fairly smoothly. Like I said, this may be sort of petty and it is a performace issue, versus my initial problem, of how do you even do non-blocking ssl :-) I have no idea if this is even the correct approach since, I just popped the hood up and started munging about until it worked. No books on POE/Tk or even POE yet. I am beginning to think POE is neater than sliced bread though a lot of stuff like getting it to work with PerlApp border on the obscure.
Re: Tk POE SSL Win32 help
by hiseldl (Priest) on Jul 30, 2003 at 13:14 UTC

    If you just want Tk to get updated, you can add update after you insert your text. e.g.

    sub send { tie (*SSL, "Net::SSLeay::Handle", "www.openssl.org", "443") or die "error in tie\n"; if (\*SSL) { print SSL "GET http://index.html \r\n"; } while (my $buf = <SSL>) { $txt->insert('end',$buf); ##### Update the Text Widget $txt->update; } }
    Or, if you want to update Tk while it is in a loop, possibly only idling, then try putting $mw->DoOneEvent; inside the loop. This may be what you need to do to get your app working with POE.

    HTH.

    --
    hiseldl
    What time is it? It's Camel Time!

      Thanks for the suggestion. I tried your suggestion in the blocking example and also in the non-blocking example and it did not make a difference. But I appreciate the input.
      JamesNC