I'm going to mostly answer my own question here.
It looks like there's nothing off-the-shelf that implements a loopback socket. If someone finds something, please let me know.
However, there is a way (at least on my win32 box) that will tie a pair of sockets together without the need for multithreading.
The magic function is called
socketpair. The docs say that some pipes are implemented by way of this function call (but even if this is true on win32, the resultant objects were not select()able, so they were of no use to me). The socketpair interface creates two genuine sockets and ties them together for you.
I've taken an example using socketpair() and updated it to use IO::Handle objects, which can be easily passed around to other parts of the code. I also demonstrated the use of select() on the socket handles. I didn't call shutdown() on either handle, so they can both read/write from/to each other (refer to perldoc -f socketpair to see an example of shutdown()).
#!perl -w
use strict;
use Socket; # for AF_UNIX, SOCK_STREAM, PF_UNSPEC
use IO::Handle; # for autoflush and object constructor
use IO::Select; # to demonstrate select()ability
my $line;
my $child = IO::Handle->new();
my $parent = IO::Handle->new();
socketpair($child, $parent, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
or die "socketpair: $!";
my %names =
(
$parent->fileno() => 'Parent',
$child ->fileno() => 'Child',
);
$child ->autoflush(1);
$parent->autoflush(1);
my $sel = IO::Select->new( $child, $parent );
$child ->print( "Hello, Parent\n" );
$parent->print( "Hello, Child\n" );
my @ready = $sel->can_read(0.1);
print "There are ${\$sel->count} readable handles\n";
foreach my $ready ( @ready )
{
my $name = $names{ $ready->fileno() };
print "$name receives: " . $ready->getline();
}
$child->close();
$parent->close();