Hot Pastrami has asked for the wisdom of the Perl Monks concerning the following question:
Hello!
I'm trying to find information on using sockets to communicate between 2 Perl scripts running on the same machine, but I've had little luck to date... that info which I can find is all relating to IP sockets over the Internet. The Camel book has some, but written in a way that could make a sockets novice openly weep (for instance: "NAME should be a packed network address of the proper type for the socket"). I've heard rumors that the Perl Cookbook has good examples of it, but my local Barnes and Noble didn't have that one in stock, so I thought I'd see if anyone here could offer help.
Can anyone possibly trouble themselves to post snippets of what the two scripts might look like to pass info between one another via sockets? Although they're on the same machine, one will play a server role, the other a client... the server will wait for and respond to requests from the client. I can figure out the error checking and ugly details, I just need to catch a glimpse of the basic concept in code.
Thanks a whole bunch,
Alan "Hot Pastrami" Bellows
-Sitting calmly with scissors-
Re: Single-machine IPC via sockets and other things to say in the dark
by BastardOperator (Monk) on Sep 14, 2000 at 01:25 UTC
|
This uses Unix domain sockets, it's from the perlipc manpage.
you didn't specify what you were looking for
#!/usr/bin/perl -w
# The client
use Socket;
use strict;
my ($socky, $line);
$socky = shift || '/tmp/mysock';
socket(SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!";
connect(SOCK, sockaddr_un($socky)) || die "connect: $!";
while (defined($line = <SOCK>)) {
print $line;
}
exit;
#################
#!/usr/bin/perl -wT
# The server
use Socket;
use strict;
use Carp;
BEGIN {
$ENV{PATH} = '/usr/ucb:/bin';
}
sub logit {
print "$0 $$: @_ at ", scalar localtime, "\n";
}
my $NAME = '/tmp/mysock';
my $uaddr = sockaddr_un($NAME);
my $proto = getprotobyname('tcp');
socket(Server,PF_UNIX,SOCK_STREAM,0) || die "socket: $!";
unlink($NAME);
bind (Server, $uaddr) || die "bind: $!";
listen(Server,SOMAXCONN) || die "listen: $!";
logit "server started on $NAME";
my $waitedpid;
sub REAPER {
$waitedpid = wait;
$SIG{CHLD} = \&REAPER;
logit "reaped $waitedpid" . ($? ? " with exit $?" : '');
}
$SIG{CHLD} = \&REAPER;
for ($waitedpid = 0;
accept(Client,Server) || $waitedpid;
$waitedpid = 0, close Client) {
next if $waitedpid;
logit "connection on $NAME";
spawn sub {
print "Hello there, it's now ", scalar localtime, "\n";
exec '/usr/games/fortune' or die "can't exec fortune:
+$!";
};
}
| [reply] [d/l] |
|
| [reply] |
RE:
by Hot Pastrami (Monk) on Sep 14, 2000 at 01:19 UTC
|
Merlyn:
You are right, however the reason I want to know how to manipulate the sockets directly is because A) I need to accomplish this interaction for a current project, and B) I want to understand the details so I can be the one writing the modules one day (hehe).
So, if anybody's got a minute to slap up some socket code, why I'd be just as happy as a... well, happy anyway.
Alan "Hot Pastrami" Bellows
-Sitting calmly with scissors- | [reply] |
|
Okay, responding point by point:
A) I need to accomplish this interaction for a current project
The two modules are available today. I show many examples of their usage
in my WT
columns, as do many other tutorials.
B) I want to understand the details so I can be the one writing the modules one day
Good, then you'll want to study good code that does useful things. The source
to these modules is well documented and less buggy than almost anything else
you'll see on the net. So use the modules, then trace down inside to see what
they're doing.
Do not attempt to build new technology without understanding existing technology.
Reinventing the wheel is fine as long as you don't do it ignorantly.
-- Randal L. Schwartz, Perl hacker
| [reply] |
|
That's true, examining the code may wield some useful stuff. By point A I wasn't implying that the modules weren't available, I was just describing how the need to get it done was only half my motivation, next to the need to understand. Turn, turn, turn.
Alan "Hot Pastrami" Bellows
-Sitting calmly with scissors-
| [reply] |
Re: IPC via sockets
by ncw (Friar) on Sep 14, 2000 at 01:20 UTC
|
If you want an easy to use perl only way of doing this
then look at Net::Daemon, and the related
RPC::pServer and Net::pRPC::Client.
It comes with a simple example of a calculator server
which is a few dozen lines of perl. You might prefer this
to merlyn's solution as it is probably lower overhead. Less
buzzword friendly though ;-)
TIMTOWDI/YMMV/IMHO/ETC | [reply] |
Re: intramachine IPC via sockets
by merlyn (Sage) on Sep 14, 2000 at 01:06 UTC
|
Again, I can't overemphasize the advantage of using a well-known-protocol for the communication. In this case, my favorite round-trip of choice is HTTP. Look
into creating a server with HTTP::Daemon, and then your client can
perform transactactions with easily-generated LWP::UserAgent objects.
-- Randal L. Schwartz, Perl hacker | [reply] |
RE:
by Fastolfe (Vicar) on Sep 14, 2000 at 17:42 UTC
|
Generally stuff made for the Internet will always work on the local host as well. You can set up "Internet" sockets and do IPC that way, just connecting to 'localhost' to do the deed.
Generally, however, if you want to limit your process's interaction to processes running on the local machine, you should consider Unix domain sockets, which work a lot like Internet sockets, but you listen on a special file, and have your other process "connect" to this file.
Both of these options have the added benefit/drawback of being able to serve any type of client that wants to interact with your "server" script, including clients that don't have any business doing this. If this is a problem, you may want to look into shared memory pools or pipes.
The perlipc man page has some great example code. | [reply] |
|
|