Sending HASH over TCP

Discussion in 'Perl Misc' started by Brad, Feb 14, 2004.

  1. Brad

    Brad Guest

    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::Dumper
    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::Dumper;
    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::Dumper::pair = " : "; # specify hash key/value
    separator
    $Data::Dumper::Indent = 0;
    # send something over the socket,
    print $socket Dumper(\%TEST);

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

    Server
    ---------------------
    use Data::Dumper;
    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::Dumper::pair = " : "; # specify hash key/value
    separator
    #$Data::Dumper::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-Dumper-2.121/Dumper.pm ) or in the
    perldoc.

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

    Thanks,
    Brad
     
    Brad, Feb 14, 2004
    #1
    1. Advertising

  2. Brad

    Ben Morrow Guest

    (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::Dumper
    > 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::Dumper;
    > 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::Dumper::pair = " : "; # specify hash key/value
    > separator


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

    > $Data::Dumper::Indent = 0;
    > # send something over the socket,
    > print $socket Dumper(\%TEST);
    >
    > # and terminate the connection when we're done.
    > close($socket);
    > ---------------------
    >
    > Server
    > ---------------------
    > use Data::Dumper;
    > 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::Dumper::pair = " : "; # specify hash key/value
    > separator
    > #$Data::Dumper::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::s::t, $a::n::eek:::t::h::e::r, $P::e::r::l, $h::a::c::k::e::r, $.
     
    Ben Morrow, Feb 14, 2004
    #2
    1. Advertising

  3. Brad

    Chris Guest

    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::Dumper
    > 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::Dumper;
    > 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::Dumper::pair = " : "; # specify hash key/value
    > separator
    > $Data::Dumper::Indent = 0;
    > # send something over the socket,
    > print $socket Dumper(\%TEST);
    >
    > # and terminate the connection when we're done.
    > close($socket);
    > ---------------------
    >
    > Server
    > ---------------------
    > use Data::Dumper;
    > 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::Dumper::pair = " : "; # specify hash key/value
    > separator
    > #$Data::Dumper::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-Dumper-2.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::Dumper::pl2xml() 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")
     
    Chris, Feb 14, 2004
    #3
  4. Brad

    Brad Walton Guest

    > 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);
     
    Brad Walton, Feb 14, 2004
    #4
  5. Brad

    Ben Morrow Guest

    "Brad Walton" <> 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'
     
    Ben Morrow, Feb 14, 2004
    #5
  6. Brad

    Brad Walton Guest

    > I recommended using nstore_fd and fd_retrieve for several reasons:
    > ...


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

    Brad
     
    Brad Walton, Feb 15, 2004
    #6
  7. Brad

    Mina Naguib Guest

    -----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::Dumper::pl2xml() 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-----
     
    Mina Naguib, Feb 16, 2004
    #7
  8. Brad

    Brad Walton Guest

    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::Dumper::pl2xml() 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-----
     
    Brad Walton, Feb 16, 2004
    #8
  9. Brad

    Rocco Caputo Guest

    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/
     
    Rocco Caputo, Feb 16, 2004
    #9
  10. Brad

    Anno Siegel Guest

    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::Dumper::pl2xml() 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
     
    Anno Siegel, Feb 16, 2004
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Bob Garbados

    sending xml over tcp/ip

    Bob Garbados, Jan 5, 2005, in forum: ASP .Net
    Replies:
    7
    Views:
    13,799
    Joerg Jooss
    Jan 7, 2005
  2. Tomek Gruca
    Replies:
    15
    Views:
    5,422
  3. Jack
    Replies:
    6
    Views:
    571
    Old Wolf
    Mar 28, 2007
  4. Jack

    Sending a struct over TCP

    Jack, Mar 30, 2007, in forum: C Programming
    Replies:
    2
    Views:
    476
    Tor Rustad
    Mar 30, 2007
  5. rp
    Replies:
    1
    Views:
    543
    red floyd
    Nov 10, 2011
Loading...

Share This Page