Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Sending HASH over TCP

Reply
Thread Tools

Sending HASH over TCP

 
 
Brad
Guest
Posts: n/a
 
      02-14-2004
I have been working on this for a few days now, and still feel stuck.
I have a large HASH which I need to send via TCP to a server. I need
to use IO::Socket::INET for the TCP connection. While there is
probably a _better_ way, I have been playing around with Data:umper
convert the HASH, then rebuild it on the other end. The problem is I
cannot seem to rebuild the data.

Code:

Client (sending HASH)
---------------------
use Data:umper;
use IO::Socket::INET;

$TEST{'test'}{'test1'} = 1;
$TEST{'test2'}{'test3'} = 2;

$socket = IO::Socket::INET->new(PeerAddr => localhost,
PeerPort => 2002,
Proto => "tcp",
Type => SOCK_STREAM)
or die "Couldn't connect to $remote_host:$remote_port : $!\n";

$Data:umper:air = " : "; # specify hash key/value
separator
$Data:umper::Indent = 0;
# send something over the socket,
print $socket Dumper(\%TEST);

# and terminate the connection when we're done.
close($socket);
---------------------

Server
---------------------
use Data:umper;
use IO::Socket::INET;

$server = IO::Socket::INET->new(LocalPort => 2002,
Type => SOCK_STREAM,
Reuse => 1,
Listen => 10 ) # or SOMAXCONN
or die "Couldn't be a tcp server on port $server_port: $!\n";

while ($client = $server->accept()) {
$data = <$client>;
#print "$data\n";
#$Data:umper:air = " : "; # specify hash key/value
separator
#$Data:umper::Indent = 0;
#eval $data;
print Dumper $data;
}

close($server);
---------------------

I have tried other methods of re-building the hash on the server-end.
The answer is probably right in front of me, but I just don't see it
on the module's page (
http://search.cpan.org/~ilyam/Data-D....121/Dumper.pm ) or in the
perldoc.

Any help, or any ideas for a better solution, is appreciated.

Thanks,
Brad
 
Reply With Quote
 
 
 
 
Ben Morrow
Guest
Posts: n/a
 
      02-14-2004

(Brad) wrote:
> I have been working on this for a few days now, and still feel stuck.
> I have a large HASH which I need to send via TCP to a server. I need
> to use IO::Socket::INET for the TCP connection. While there is
> probably a _better_ way, I have been playing around with Data:umper
> convert the HASH, then rebuild it on the other end. The problem is I
> cannot seem to rebuild the data.
>
> Code:
>
> Client (sending HASH)
> ---------------------
> use Data:umper;
> use IO::Socket::INET;
>
> $TEST{'test'}{'test1'} = 1;
> $TEST{'test2'}{'test3'} = 2;
>
> $socket = IO::Socket::INET->new(PeerAddr => localhost,
> PeerPort => 2002,
> Proto => "tcp",
> Type => SOCK_STREAM)
> or die "Couldn't connect to $remote_host:$remote_port : $!\n";
>
> $Data:umper:air = " : "; # specify hash key/value
> separator


Why? If you want to be able to eval it, you need to leave it as =>.

> $Data:umper::Indent = 0;
> # send something over the socket,
> print $socket Dumper(\%TEST);
>
> # and terminate the connection when we're done.
> close($socket);
> ---------------------
>
> Server
> ---------------------
> use Data:umper;
> use IO::Socket::INET;
>
> $server = IO::Socket::INET->new(LocalPort => 2002,
> Type => SOCK_STREAM,
> Reuse => 1,
> Listen => 10 ) # or SOMAXCONN
> or die "Couldn't be a tcp server on port $server_port: $!\n";
>
> while ($client = $server->accept()) {
> $data = <$client>;
> #print "$data\n";
> #$Data:umper:air = " : "; # specify hash key/value
> separator
> #$Data:umper::Indent = 0;
> #eval $data;
> print Dumper $data;


You don't need to Dumper it *again*... also, ITY realise that as
you've taken out the eval it won't do owt?

> }
>
> close($server);
> ---------------------
>
> I have tried other methods of re-building the hash on the server-end.


I would strongly recommend using the Storable module, and the
functions nstore_fd and fd_retrieve. I have had success with this in
the past. Each fd_retrieve will get one whole structure, so you can
push several through the socket one after the other and they won't get
mixed up.

Ben

--
$.=1;*g=sub{print@_};sub r($$\$){my($w,$x,$y)=@_;for(keys%$x){/main/&&next;*p=$
$x{$_};/(\w)::$/&&(r($w.$1,$x.$_,$y),next);$y eq\$p&&&g("$w$_")}};sub t{for(@_)
{$f&&($_||&g(" "));$f=1;r"","::",$_;$_&&&g(chr(0012))}};t #
$J::u::t, $a::n:::t::h::e::r, $P::e::r::l, $h::a::c::k::e::r, $.
 
Reply With Quote
 
 
 
 
Chris
Guest
Posts: n/a
 
      02-14-2004
Brad wrote:
> I have been working on this for a few days now, and still feel stuck.
> I have a large HASH which I need to send via TCP to a server. I need
> to use IO::Socket::INET for the TCP connection. While there is
> probably a _better_ way, I have been playing around with Data:umper
> convert the HASH, then rebuild it on the other end. The problem is I
> cannot seem to rebuild the data.
>
> Code:
>
> Client (sending HASH)
> ---------------------
> use Data:umper;
> use IO::Socket::INET;
>
> $TEST{'test'}{'test1'} = 1;
> $TEST{'test2'}{'test3'} = 2;
>
> $socket = IO::Socket::INET->new(PeerAddr => localhost,
> PeerPort => 2002,
> Proto => "tcp",
> Type => SOCK_STREAM)
> or die "Couldn't connect to $remote_host:$remote_port : $!\n";
>
> $Data:umper:air = " : "; # specify hash key/value
> separator
> $Data:umper::Indent = 0;
> # send something over the socket,
> print $socket Dumper(\%TEST);
>
> # and terminate the connection when we're done.
> close($socket);
> ---------------------
>
> Server
> ---------------------
> use Data:umper;
> use IO::Socket::INET;
>
> $server = IO::Socket::INET->new(LocalPort => 2002,
> Type => SOCK_STREAM,
> Reuse => 1,
> Listen => 10 ) # or SOMAXCONN
> or die "Couldn't be a tcp server on port $server_port: $!\n";
>
> while ($client = $server->accept()) {
> $data = <$client>;
> #print "$data\n";
> #$Data:umper:air = " : "; # specify hash key/value
> separator
> #$Data:umper::Indent = 0;
> #eval $data;
> print Dumper $data;
> }
>
> close($server);
> ---------------------
>
> I have tried other methods of re-building the hash on the server-end.
> The answer is probably right in front of me, but I just don't see it
> on the module's page (
> http://search.cpan.org/~ilyam/Data-D....121/Dumper.pm ) or in the
> perldoc.
>
> Any help, or any ideas for a better solution, is appreciated.
>


Aside from Ben Morrow's solution (which I wish I had the time to try),
if you are stuck on a "Dumper()" solution, you might get more mileage
out of the XML:umper:l2xml() and xml2pl() routines. Write yourself
a psuedo-web service that passes XML structures back and forth.
pl2xml() and xml2pl() will handle this rightly.

Without digging into your code too much (seeing as it's way past my bed
time) and surmising WHY you might be trying to accomplish this in the
first place, you may even have your wants satisfied by tossing the
structure passing altogether and writing a real web service using
XML-RPC. Check out Frontier::RPC2 for more information. XML-RPC in
Perl is painless to setup and quite powerful (though inherently insecure
I have to admit). You can setup XML-RPC on your port 2002 if you want.

Chris
-----
Chris Olive
chris 0at0 00-00-00 technologEase 0dot0 com
http://www.technologEase.com
(pronounced "technologies")
 
Reply With Quote
 
Brad Walton
Guest
Posts: n/a
 
      02-14-2004
> I would strongly recommend using the Storable module, and the
> functions nstore_fd and fd_retrieve. I have had success with this in
> the past. Each fd_retrieve will get one whole structure, so you can
> push several through the socket one after the other and they won't get
> mixed up.
>
> Ben


Thanks! This works great, and is very simple to use. I got it working with
the serialize [freeze, thaw] options. Here is what it looks like:

Client
-----------------
use Storable qw(freeze);
use IO::Socket::INET;

$TEST{'test'}{'test1'} = 1;
$TEST{'test2'}{'test3'} = 2;

$socket = IO::Socket::INET->new(PeerAddr => localhost,
PeerPort => 2002,
Proto => "tcp",
Type => SOCK_STREAM)
or die "Couldn't connect to $remote_host:$remote_port : $!\n";

# Serializing to memory
$serialized = freeze \%TEST;
print $socket $serialized;

# and terminate the connection when we're done.
close($socket);



Server

------------------------

use Storable qw(thaw);
use IO::Socket::INET;

$server = IO::Socket::INET->new(LocalPort => 2002,
Type => SOCK_STREAM,
Reuse => 1,
Listen => 10 ) # or SOMAXCONN
or die "Couldn't be a tcp server on port $server_port: $!\n";

while ($client = $server->accept()) {
$data = <$client>;
%TEST = %{ thaw($data) };

foreach my $key (keys %TEST) {
print "\nValues for $key in \%TEST:\n";
foreach my $key2 (keys %{$TEST{$key}}) {
print "\t$key2 => ", ${$TEST{$key}}{$key2}, "\n";
}
}
}

close($server);


 
Reply With Quote
 
Ben Morrow
Guest
Posts: n/a
 
      02-14-2004
"Brad Walton" <sammie-> wrote:

I recommended using nstore_fd and fd_retrieve for several reasons:

1. you don't need to create the Storable structure in memory

2. nstore_fd creates a structure in network byte-order, which can be
important if sending data between machines of different endianness
(and does no harm otherwise)

3. fd_retrieve will find the end of the structure for you: as things
stand you are reading one \n-terminated line, which will break if
the frozen representation has "\n" in it, which is not at all
unlikely.

> Client
> -----------------


use strict;
use warnings;

> use Storable qw(freeze);


use Storable qw(nstore_fd);

> use IO::Socket::INET;


my %TEST;

> $TEST{'test'}{'test1'} = 1;
> $TEST{'test2'}{'test3'} = 2;
>
> $socket = IO::Socket::INET->new(PeerAddr => localhost,


my $socket = ...

> PeerPort => 2002,
> Proto => "tcp",
> Type => SOCK_STREAM)
> or die "Couldn't connect to $remote_host:$remote_port : $!\n";
>
> # Serializing to memory
> $serialized = freeze \%TEST;
> print $socket $serialized;


nstore_fd \%TEST, $socket;

> # and terminate the connection when we're done.
> close($socket);
>
> Server
> ------------------------


use strict;
use warnings;

> use Storable qw(thaw);


use Storable qw(fd_retrieve);

> use IO::Socket::INET;
>
> $server = IO::Socket::INET->new(LocalPort => 2002,


my $server = ...

> Type => SOCK_STREAM,
> Reuse => 1,
> Listen => 10 ) # or SOMAXCONN
> or die "Couldn't be a tcp server on port $server_port: $!\n";
>
> while ($client = $server->accept()) {


while (my $client = ...

> $data = <$client>;
> %TEST = %{ thaw($data) };


%TEST = %{ fd_retrieve $client };

> foreach my $key (keys %TEST) {
> print "\nValues for $key in \%TEST:\n";


Fix your indenting.

> foreach my $key2 (keys %{$TEST{$key}}) {
> print "\t$key2 => ", ${$TEST{$key}}{$key2}, "\n";
> }
> }
> }
>
> close($server);


Ben

--
If you put all the prophets, | You'd have so much more reason
Mystics and saints | Than ever was born
In one room together, | Out of all of the conflicts of time.
|----------------+---------------| The Levellers, 'Believers'
 
Reply With Quote
 
Brad Walton
Guest
Posts: n/a
 
      02-15-2004
> I recommended using nstore_fd and fd_retrieve for several reasons:
> ...


Thanks Ben, I will test this out. Appreciate the help!

Brad


 
Reply With Quote
 
Mina Naguib
Guest
Posts: n/a
 
      02-16-2004
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


Chris wrote:
> Aside from Ben Morrow's solution (which I wish I had the time to try),
> if you are stuck on a "Dumper()" solution, you might get more mileage
> out of the XML:umper:l2xml() and xml2pl() routines. Write yourself
> a psuedo-web service that passes XML structures back and forth. pl2xml()
> and xml2pl() will handle this rightly.


Another solution is Net::EasyTCP written by yours truly.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFAMCskeS99pGMif6wRAvi7AJ95L78w00hiBJkMTkoMM+ xms3NUAwCg5wj2
Pc6N6gtVrw8PnMvh+nmTqs8=
=ne66
-----END PGP SIGNATURE-----
 
Reply With Quote
 
Brad Walton
Guest
Posts: n/a
 
      02-16-2004
I was actually using that up until I had to make this change. Thanks, it is
a very easy-to-use module and made accomplishing my task (at that time) very
simple. Unfortunately, I could not get it to communicate with a new program
that was introduced to my project, which is not written in Perl and required
a TCP connection.

Brad


"Mina Naguib" <> wrote in message
news:BWVXb.13871$...
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
>
> Chris wrote:
> > Aside from Ben Morrow's solution (which I wish I had the time to try),
> > if you are stuck on a "Dumper()" solution, you might get more mileage
> > out of the XML:umper:l2xml() and xml2pl() routines. Write yourself
> > a psuedo-web service that passes XML structures back and forth. pl2xml()
> > and xml2pl() will handle this rightly.

>
> Another solution is Net::EasyTCP written by yours truly.
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.2.3 (GNU/Linux)
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
>
> iD8DBQFAMCskeS99pGMif6wRAvi7AJ95L78w00hiBJkMTkoMM+ xms3NUAwCg5wj2
> Pc6N6gtVrw8PnMvh+nmTqs8=
> =ne66
> -----END PGP SIGNATURE-----



 
Reply With Quote
 
Rocco Caputo
Guest
Posts: n/a
 
      02-16-2004
On Sun, 15 Feb 2004 19:19:07 -0800, Brad Walton wrote:
> I was actually using that up until I had to make this change. Thanks, it is
> a very easy-to-use module and made accomplishing my task (at that time) very
> simple. Unfortunately, I could not get it to communicate with a new program
> that was introduced to my project, which is not written in Perl and required
> a TCP connection.


Have you looked at POE, then? It deals well with TCP connections, and
POE::Filter::Reference can serialize Perl data structures in a number of
ways.

--
Roccco aputo - - http://poe.perl.org/
 
Reply With Quote
 
Anno Siegel
Guest
Posts: n/a
 
      02-16-2004
Mina Naguib <> wrote in comp.lang.perl.misc:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
>
> Chris wrote:
> > Aside from Ben Morrow's solution (which I wish I had the time to try),
> > if you are stuck on a "Dumper()" solution, you might get more mileage
> > out of the XML:umper:l2xml() and xml2pl() routines. Write yourself
> > a psuedo-web service that passes XML structures back and forth. pl2xml()
> > and xml2pl() will handle this rightly.

>
> Another solution is Net::EasyTCP written by yours truly.


....and a very fine little module it is. It hides what you don't want to be
bothered with and exposes what you want to decide. It's intuitive, so you
can use it immediately. It deserves its name.

Anno
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
hash of hash of hash of hash in c++ rp C++ 1 11-10-2011 04:45 PM
VOIP over VPN over TCP over WAP over 3G Theo Markettos UK VOIP 2 02-14-2008 03:27 PM
sending a struct over TCP Jack C++ 6 03-27-2007 11:32 PM
sending Objects and Strings over TCP/IP Tomek Gruca Java 15 01-16-2007 01:42 PM
sending xml over tcp/ip Bob Garbados ASP .Net 7 01-07-2005 07:32 AM



Advertisments