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

Hello, I have a current implementation which uses File::Tail to stream live data from a continuously written log file(from host A) to another machine(host B) using IO::Socket.
I basically listen on a socket on host B first and the start writing on host A on that socket. Everything works fine.

Now the issue is I need another log file on host C to be written to the same socket of host B. What are the possible ways for this.? I was suggested to use IO::Async on IRC. Though, I haven't gone thro' it, I'm yet curious to know if there are any other ways... looking for some inputs/ explanations on how to proceed...
  • Comment on IO::Socket/multiple connections related

Replies are listed 'Best First'.
Re: IO::Socket/multiple connections related
by tfoertsch (Beadle) on Jul 02, 2009 at 16:45 UTC
    If I understand you correctly your problem is host B. You want to read 2 streams at the same time.

    There are many solutions. The simplest is certainly a forking server. After accept()ing a new client the process calls fork(). The parent process closes the client connection and waits for the next client while the child handles the connection.

    Another way is to use select() (or IO::Select) with nonblocking IO. There are many examples on the Internet I believe.

    Then there are various event modules that do basically the same as select() but often more effectively. These come to mind: Event, Event::Lib, EV, POE, AnyEvent

    Then there are perl's ithreads. (use threads;)

    And in the end there is Coro. If I where you I'd go either with this one or code a forking server.

    Torsten

Re: IO::Socket/multiple connections related
by SuicideJunkie (Vicar) on Jul 02, 2009 at 16:50 UTC
    IO::Select could work too. Get a list of the connections that have data to read from using IO::Select->select, and then read a line from each of them before going back to wait for more input. Only read from the sockets that have something to read, and you won't block.
    my $readable = IO::Select->new; $readable->add($oneSock, $twoSock, $redSock, $blueSock); while (not $done) { my $ready = IO::Select->select($readable); foreach my $socket (@$ready) { # Deal with whatever $socket has to say } }
Re: IO::Socket/multiple connections related
by dk (Chaplain) on Jul 02, 2009 at 17:15 UTC
    In addition to the list of event frameworks kindly provided by tfoertsch, I would like to add my own IO::Lambda, which I really wish had more adoption and hope everyone else would excuse me for PRing. Anyways. If you feel like trying it, I'd be glad to provide help. Using it, your task would be written basically as such:
    use strict; use IO::Socket; use IO::Lambda qw(:all); use IO::Lambda::Socket qw(:all); my $server = IO::Socket::INET-> new( Listen => 5, LocalPort => 10000, Blocking => 0, ReuseAddr => 1, ); die $! unless $server; lambda { context $server; accept { # socket with an incoming connection my $conn = shift; # tell the loop to accept() again again; unless ( ref($conn)) { warn "accept() error:$conn\n" unless ref($conn); return; } # now read all from the new connection context $conn; readable { my $buf; my $n = sysread( $conn, $buf, 65536); unless ( defined $n) { warn "error reading:$!\n"; } elsif ( $n == 0) { warn "connection closed\n"; } else { print $buf; again; } }} }-> wait;
    Hope it helps
Re: IO::Socket/multiple connections related
by ikegami (Patriarch) on Jul 02, 2009 at 17:02 UTC
    File::Tail has native support for this. Search its documentation for the select method. It even has an example.

    Update: I thought you had mentioned you were using File::Tail. Ignore this post, it won't help you since File::Tail won't work with sockets. You need IO::Select