Data-Send-Local
view release on metacpan or search on metacpan
lib/Data/Send/Local.pm view on Meta::CPAN
#!/usr/bin/perl
#-------------------------------------------------------------------------------
# Send a block of data from one process to another on the local machine
# Philip R Brenan at gmail dot com, Appa Apps Ltd Inc, 2016-2017
#-------------------------------------------------------------------------------
package Data::Send::Local;
our $VERSION = 20180405;
use v5.8.0;
use warnings FATAL => qw(all);
use strict;
use Carp qw(confess);
use Data::Dump qw(dump);
use Data::Table::Text qw(:all);
use Socket;
#1 Send and receive
sub sendLocal($$;$) #S Send a block of data locally. Returns B<undef> on success otherwise an error message
{my ($socketName, $data, $timeOut) = @_; # Socket name (a socket file name that already exists), data, optional timeout for socket to be created - defaults to 10 seconds
if (!-S $socketName) # Wait for a bit if necessary for the socket to be created
{for(1..($timeOut//10)) {sleep 1; last if -S $socketName}
}
-S $socketName or return "No such socket: $socketName"; # Socket not available
socket(my $socket, AF_UNIX, SOCK_DGRAM, 0) or return $!;
connect($socket, sockaddr_un($socketName)) or return $!;
send($socket, dump($data), 0) or return $!;
close($socket);
undef # Return without errors
}
sub recvLocal($;$$) #S Receive a block of data sent locally. Returns the data received.
{my ($socketName, $user, $length) = @_; # Socket name (a socket file name that is created), optional username of the owner of the socket, maximum length to receive - defaults to one megabyte.
unlink $socketName; # Remove existing socket to avoid 'already in use';
makePath($socketName); # Create socket directory
socket(my $socket, AF_UNIX, SOCK_DGRAM, 0) or confess $!;
bind($socket, sockaddr_un($socketName)) or confess $!;
if ($user) # Do this to make the socket writable by some one else
{qx(chown $user:$user $socketName);
}
recv($socket, my $read, $length // 1e6, 0);
close($socket);
unlink $socketName; # Remove existing socket to force send to wait while the socket is created
my $r = eval $read; # Reconstitute data
$@ and confess $@; # Bad data block
$r # Return data
}
#-------------------------------------------------------------------------------
# Tests
#-------------------------------------------------------------------------------
sub test2()
{my $socket = 'socket'; # Socket name
my $data = 'hello'; # Data
autoflush STDOUT 1;
if ($^O !~ m/\AMSWin32\Z/) # Ignore windows
{say STDOUT "1..2";
if (fork())
{say STDOUT "ok" if Data::Send::Local::recvLocal($socket) eq $data; # Receive data
}
else
{autoflush STDOUT 1;
say STDOUT "ok" unless Data::Send::Local::sendLocal($socket, $data); # Send data without error
}
}
}
test2 unless caller;
# podDocumentation
=pod
=encoding utf-8
=head1 Name
Data::Send::Local - Send and receive a block of data between processes on the
local machine.
=head1 Synopsis
Send B<hello> between two processes running on the same machine over the
socket named B<socket>.
use Test2::Bundle::More;
my $socket = 'socket'; # Socket name
my $data = 'hello'; # Data
if (fork())
{ok Data::Send::Local::recvLocal($socket) eq $data; # Receive data
}
else
( run in 1.402 second using v1.01-cache-2.11-cpan-71847e10f99 )