Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl socket sending hash

Tags:

sockets

perl

I am trying to create a socket client in Perl. The server side is a C program running on the local host.

I have to send a hash over the socket. Here is the piece of code I am using.

sub applyGlobalConfig {
    my ($globalConfig, $ignoreData) = @_;

    my $socket = IO::Socket::INET->new(PeerAddr => $PEER_HOST,
                                       PeerPort => $PEER_PORT,
                                       Proto    => "tcp",
                                       Type     => SOCK_STREAM)
          or die "Couldn't connect to $PEER_HOST:$PEER_PORT : $@\n";

    my $reconfigResult;

    print $socket "$113\n";

    close($socket);

    unless ($reconfigResult) {
        return 0;
    }

    return ERR_NULL;
}

Now, the question I have is, the $globalConfig will contain a hash reference, and I want to send this over a socket. I am unable figure out. I googled and found some reference to Dumper but couldn’t understand much. How do I send the hash over?

like image 850
Sreeram Ravinoothala Avatar asked Nov 28 '25 22:11

Sreeram Ravinoothala


2 Answers

To send a data structure over a socket you have to "serialize" it into a byte stream. Then the receiving program has to deserialize it to reassemble the data structure. If the receiving program is expecting the stream to be in a specific form, the sending program must produce the expected format.

If you are writing both sides, then you can choose a serialization format that makes sense for your situation, such as JSON or XML, either of which can represent a Perl hash. However, without knowing much more detail about your specific situation, this is about all that can be provided in the way of an answer.

like image 101
Jim Garrison Avatar answered Dec 01 '25 13:12

Jim Garrison


I'd prefer to use Storable module for this. Example:

Receive-side:

use strict;
use IO::Socket::INET;
use Storable;
use Data::Dumper;

my   $sock = IO::Socket::INET->new(Listen    => 5, LocalAddr => 'host',
                                 LocalPort => 9000,  Proto     => 'tcp');
while( my $s = $sock->accept ) {
    my $struct = Storable::fd_retrieve($s);
    print Dumper($struct);
}

Send-side:

use strict;
use IO::Socket::INET;
use Storable;

my   $sock = IO::Socket::INET->new(PeerAddr => 'host',  PeerPort => 9000,
                 Type     => SOCK_STREAM, Proto     => 'tcp') || die "Fail: $!";
my $struct = {
    a => 1,
    b => [2,3,4]
};
Storable::nstore_fd($struct, $sock);

Tested by sending from i386 Linux to amd64 FreeBSD.

Also you can use Data::Dumper to make string from hash and then send over network but its dirty and buggy method.

UPD:

But, I am struggling how to convert the values in the hash on perl side to a string separated by space.

Try to use join/map combination:

my $serialized = join("\n", map { "$_ ".$struct->{$_} } keys %$struct)."\n";

Probably on C side its easier to use null-terminated string:

my $keyvalue_count = scalar keys(%$struct);
my $serialized = join("\0", map { "$_\0".$struct->{$_} } keys %$struct)."\0";

In this simple case i'd prefer to use last variant since its native to C.

like image 33
PSIAlt Avatar answered Dec 01 '25 13:12

PSIAlt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!