dpmott has asked for the wisdom of the Perl Monks concerning the following question:

I'm looking for a loopback socket, which will work on a win32 system.

I'd be happy to find something in the commonly installed modules or on CPAN, but I'm willing to write a subclass if I can get a few pointers.

Basically, I need an object that behaves like a socket (INET variety if it matters). It needs to play nice with IO::Select, especially when it has data. The magic that I need is that I'd like to sysread() everything that I syswrite() or print() to it.

I tried to look up something like this, but came up empty. I tried using a filehandle opened to an in-memory string, but it didn't work with sysread() and was not select()able. I also tried pipe()'d IO::Handles, but they were not select()able (or pipes are broken on win32, not sure which).

Does anyone know where I could find a module that implements such an object? Or, alternatively, a straightforward way to write my own?

Thanks,
-dpmott
  • Comment on Looking for a loopback socket for win32

Replies are listed 'Best First'.
Re: Looking for a loopback socket for win32
by Corion (Patriarch) on Aug 16, 2005 at 06:53 UTC

    How about actually using a socket, then?

    What kind of problem are you trying to solve?

    Nothing except true INET sockets will be selectable on Win32 due the different way sockets are implemented.

      If only a true socket is selectable, then I will likely have to approach it that way.

      I was hoping that I could just have one object, to which I could write, and then read what I just wrote. By using normal sockets, I'll have to put together a pair of them, and in order to do that, I'll have to set one up for listen mode and then accept() on it. I think that I'll have to be multithreaded to do that, which I've managed to avoid thus far. That, if nothing else, is the reason why I'm not eager to bite the bullet.

      Perhaps I should ask a different question... is there a way (without multithreading) to connect two sockets to talk to each other?

      If I could work that bit of magic, then I could make a class that looks like just one object, but I could sysread() on one socket and syswrite() on the other, giving the appearance of a loopback or echoing socket.
Re: Looking for a loopback socket for win32
by dpmott (Scribe) on Aug 16, 2005 at 17:49 UTC
    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();