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

I want to receive an XML packet using IO::Sockets. I have a script to do so but it cuts out sometimes causing the program to terminate. This is bad since it will be incorporated ino a much larger program. The script I have now is:
#! perl -slw use strict; use IO::Socket; use XML::Simple; $SIG{PIPE} = "IGNORE"; $\="\n"; my $img = '"http://updraft.unl.edu/~uas/uas/uas.png"'; my $post_time; my $test; my $xs = XML::Simple->new( RootName=>'Telemetry', XMLDecl => 1); my $check = 0; for (;;){ my $tele_client = IO::Socket::INET->new( 'localhost:12345' ) or pr +int $!; if ($tele_client){ while( <$tele_client>) { ################################# print "@@@ started @@@"; if ($tele_client){ print "*** Recv UA ***"; $tele_client->recv($test, 100000000); print $test; #UAS Functions: print "Reading in XML"; my $uasdata = $xs->XMLin($test); print "--- XML ---"; print Dumper($uasdata); if ("$uasdata->{VehicleID}" eq 'Velocity'){ #Open Placefile open UASPF,'>',"/home/uas/public_html/uas/uaspf.tx +t.bak" or die "Cannot Open File uavpf.txt.bak!"; #open UASPF,'>',"uaspf.txt.bak" or die "Cannot Ope +n File uavpf.txt.bak!"; &time; #print placefile elements print UASPF "Title: UAS GPS Position"; print UASPF "Threshold: 999"; print UASPF "RefreshSeconds: 2"; print UASPF "Iconfile: 1, 22, 21, 10, 14, $img\n"; print UASPF "Icon: $uasdata->{GPS}->{Latitude}, $u +asdata->{GPS}->{Longitude}, $uasdata->{GPS}->{Heading}, 1, 1, $post_t +ime Latitude: $uasdata->{GPS}->{Latitude} Longitude: $uasdata->{GPS}- +>{Longitude} Heading: $uasdata->{GPS}->{Heading} Speed: $uasdata->{Ai +rData}->{TrueAirSpeed} cm/s"; close UASPF; rename("/home/uas/public_html/uas/uaspf.txt.bak", +"/home/uas/public_html/uas/uaspf.txt") or die"Unable to replace: $!"; #rename("uaspf.txt.bak", "uaspf.txt") or die"Unabl +e to replace: $!"; print "*** UA Done ***"; } } } } print "SLEEP"; sleep 5; }
The program stops here: $tele_client->recv($test, 100000000); The only way I have thought to fix it is by increasing the size of the received data. Is there a better way to do this?

Replies are listed 'Best First'.
Re: Receiving an XML packet using IO::Socket
by jettero (Monsignor) on Jun 03, 2008 at 17:28 UTC

    Why use raw IO::Sockets? Why not Net::Server, Net::Daemon, or even HTTP::Server::Simple? I think they'd save you a lot of trouble and do all the nasty parts for you.

    I'm particularly fond of Net::Server. You basically read from STDIN and write to STDOUT. It's identical to console programing in most respects.

    -Paul

Re: Receiving an XML packet using IO::Socket
by moritz (Cardinal) on Jun 03, 2008 at 17:31 UTC
    So your program is blocking while it tries to read about 100MB (or until an EOF returns) from a socket. Apparently the server on the other side doesn't deliver that data.

    You could just set a timeout, so a recv will fail if it doesn't provide any data. Or you could investigate non-blocking IO. What do you want?

Re: Receiving an XML packet using IO::Socket
by pc88mxer (Vicar) on Jun 03, 2008 at 18:04 UTC
    What is your protocol? Is a network connection limited to one request (one XML packet)?

    I see a potential problem with mixing buffered I/O with recv:

    while( <$tele_client>) { if ($tele_client){ $tele_client->recv($test, 100000000);
    For stream sockets I believe send is equivalent to syswrite and recv is equivalent to sysread. In any case, mixing the two forms of I/O is not a good idea. You are aware that <$tele_client> will read a line from the socket connection, right?

    If your protocol is limited to one request per connection, why not just slurp in the entire XML packet:

    $test = do { local $/; <$tele_client> }; my $uasdata = $xs->XMLin($test); ...
Re: Receiving an XML packet using IO::Socket
by zentara (Cardinal) on Jun 03, 2008 at 18:33 UTC