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

I'm having some fairly strange problems trying to use SOAP::Lite with Windows. I'm running a Linux server and some Linux clients, and everything works perfectly. However, when I use the same client code on Windows, it doesn't work right.

The first problem I encountered was trying to use SOAP::Transport::TCP. I started my server just like the perldoc said, like so:

my $daemon = SOAP::Transport::TCP::Server -> new(LocalAddr => 'localhost', LocalPort => $port, Listen => 5, Reuse => 1)->dispatch_to('RecommendServer'); print "Contact to SOAP server at " . join(':', $daemon->sockhost, $daemon->sockport) . $/; $daemon->handle;
Connecting to this server with the Linux client, like:
my $soap_response = SOAP::Lite-> uri("http://tako:$port/RecommendServer")-> proxy("tcp://tako:$port") ->similarity_ranked($user);
works fine; I can access the objects I want, get stuff over the network, whatever. No problem. But then I try the same code on the Windows box, and I get the error: IO::Socket::INET: connect: Unknown error at tk3 line 199 (tk3 is my script; line 199 is the line above).

So that was pretty irritating. I decided to try using the HTTP server rather than the TCP server:

SOAP::Transport::HTTP::Daemon ->new(LocalPort => $port, DEBUG => 1) ->dispatch_to('RecommendServer') ->handle;
Connecting from the client like so:
my $soap_response = SOAP::Lite-> uri("http://tako:$port/RecommendServer")-> proxy("http://tako:$port")->similarity_ranked($user);
worked great on Linux as usual. Then I tried it on Windows, and it worked! The first time. The second time (in the same session) I tried, it froze up. More accurately, it seemed to open a connection to the server and then block. No other clients (whether Linux or Windows) could connect. After about a minute and a half, the client finally manages to request the data it wants and stops blocking, allowing other clients to happily connect again.

I've tried using SOAP::Lite with +trace => qw(all), but the client just prints my debug message "contacting server" and then sits there until the connection actually works. I can't figure out how enable debugging on the server.

Thanks for any help!

Daniel Ashbrook

Replies are listed 'Best First'.
Re: SOAP::Lite in Windows
by particle (Vicar) on Jul 28, 2003 at 15:41 UTC
    I've tried using SOAP::Lite with +trace => qw(all), but the client just prints my debug message "contacting server" and then sits there until the connection actually works. I can't figure out how enable debugging on the server.

    you need to do tracing on the server. i prefer using a callback to send tracing info to an existing log:

    package My::SOAP::Server; BEGIN { ## configure log here (i like Log::Log4perl) } use SOAP::Lite +trace => [ all => sub{ print $log join( "\n\t" => 'ACK!', @_ ), "\n\n" }, ];

    by the way, i find using dispatch_from on your client reduces cross-platform migration errors. i use it now in my clients, and they work on both windows and solaris.

    ~Particle *accelerates*

      Thanks for the hint for logging on the server, but no go. The logging works, however the log gives no information until the client actually connects, a minute and a half later.

      I'm using Tk in my client; I wonder if that might be a problem? I threw together some sample code that breaks just as much as my full code, and it's pretty darn simple:

      The sever:

      #!/usr/bin/perl -w use strict; use SOAP::Transport::HTTP; SOAP::Transport::HTTP::Daemon->new(LocalPort => 3004) ->dispatch_to('My::Soapy')->handle; package My::Soapy; sub testy { return "happy!"; }

      And the client:

      #!/usr/bin/perl -w use strict; use SOAP::Lite; use Tk; my $main = MainWindow->new; my $button = $main->Button(-text => 'go!', -command => \&get); $button->pack; MainLoop; sub get { print "got: " . SOAP::Lite->uri('http://tako:3004/My/Soapy') ->proxy('http://tako:3004')->testy()->result . $/; }

      My only reply on the SOAP::Lite mailing list (thus far) suggests that maybe Windows isn't closing the socket, but I'm not sure how to check on that, or force it to close.

      Daniel Ashbrook

        tk is not the problem. i took your example code and recreated your problem in my win2000 environment. as for creating a good example of the problem, well done! that made this problem easy for me to track down. i wish all my developers could boil their problems down to a examples this small.

        back to the problem at hand. two small changes will fix this right up--one on the server, and one on the client.

        here is my modified client. notice i modified the uri to point to a valid urn. this is very important--the urn is relative to the host, so absolute path really screws it up. in fact, i'm surprised it resolved it at all! there should probably be better error checking for valid urns in SOAP::Lite, to prevent others from making this mistake as well.

        #!/usr/bin/perl -w use strict; use SOAP::Lite; use Tk; my( $server, $port, $urn )= qw(localhost 3004 urn://My/Soapy); my $main= MainWindow->new; my $button= $main->Button( -text => 'go!', -command => \&get, )->pack; MainLoop; sub get { print "got: ", ## SOAP::Lite->uri('http://tako:3004/My/Soapy') SOAP::Lite->uri($urn) ->proxy("http://${server}:$port") ->testy() ->result, $/; }

        okay, i lied. actually the only change you need was to the client. but as i mentioned before, i prefer dispatch_with over dispatch_to, so i've modified your server to use that style. i prefer dispatch_with both because you can set your server up with multiple urns, handled by multiple packages; and because the urn and handler are paired in a hash, they are self-documenting.

        #!/usr/bin/perl -w use strict; use SOAP::Transport::HTTP; my( $server, $port, $urn, $handler )= qw(localhost 3004 urn://My/Soapy My::Soapy); SOAP::Transport::HTTP::Daemon ->new( LocalAddr => $server, LocalPort => 3004, )->dispatch_to('My::Soapy')->handle; ## )->dispatch_with({ $urn => $handler }) ->handle or die 'a horrible death!'; package My::Soapy; sub testy() { 'happy!' }

        by the way, you should always test for errors on your server, even in an example script. and if you are using a perl >= 5.006, you should consider use warnings over -w.

        ~Particle *accelerates*

Re: SOAP::Lite in Windows
by mod_alex (Beadle) on Jul 29, 2003 at 07:23 UTC
    Dear Daniel
    First of all I'd like to suggest you to rewrite the client in the next way :
    #!/usr/bin/perl -w use strict; use SOAP::Lite; use Tk; use Data::Dumper; my $main = MainWindow->new; my $button = $main->Button(-text => 'go!', -command => \&get); $button->pack; MainLoop; sub get { my $soapObj = SOAP::Lite->uri('http://devzone:3004/My/Soapy') ->proxy('http://tako:3004'); my $result = $soapObj->testy(); unless ($result->fault()) { print "result : " . $result->result() . "\n"; } else { print "faultcode : " . $result->faultcode() . ", faultctring : " . $result->faultstring() . "\n"; } }
    I've checked that client and it works fine for my windows computer.
    I guess there is a problem with network layer.
    Try to run "ping tako" from your windows comp.
    --
    Alex
      Hi Alex,

      Thanks for the suggestions. I gave your code a try, and I'm getting the same problems as in my reply to Particle above: error messages about Tk::Errror: 500 Can't read entity body. It of course works perfectly under Linux.

      I'd certainly buy that Windows has bugs in its network layer. Trying "ping tako" works fine.

      Thanks a bunch,

      Daniel Ashbrook