home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!olivea!tymix!grimoire!mooring
- From: mooring@grimoire.tymnet.com (Ed Mooring)
- Newsgroups: comp.lang.perl
- Subject: Re: Multiple listeners to a data source
- Message-ID: <2164@tymix.Tymnet.COM>
- Date: 29 Jul 92 18:36:01 GMT
- References: <1992Jul29.145654.6622@nstn.ns.ca>
- Sender: usenet@tymix.Tymnet.COM
- Organization: BT Tymnet Bit Bucket Brigade
- Lines: 249
- Nntp-Posting-Host: grimoire
-
- In article <1992Jul29.145654.6622@nstn.ns.ca> daniel@nstn.ns.ca (Daniel MacKay) writes:
- >Hello!
- >
- >I will be bringing up a data source in a few days, (it's a connection to a
- >weather satellite) that I'd like people to be able to just telnet to a port
- >on my machine, and listen in on- say, five or ten people, all with the same
- >data scrolling by, kind of like a broadcast ticker tape machine.
- >
- >I'm looking for suggestions about how to do it. The boneheaded solution is
- >to set up a "tail -f" on a file that the data's being dumped into- but I
- >was hoping to not save the data- it's jillions of lines a day.
- >
- >The data will be arriving on a TCP port to which a Perl program will be
- >attached; the program will pull out selected data sets and pop them into
- >individual files. But I'd also like to make the raw data available to
- >whoever wants it in real time.
-
- Here's something I call a broadcast server that does almost exactly
- what you want. Right now it reads stdin, and writes to whomever
- makes a connection to it. It also has some primitive security,
- and an even more primitive man page.
- -------------------- snip here--------------------
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: /home/grimoire/a/mooring/errlogger/bcast
- # /home/grimoire/a/mooring/errlogger/bcast.1
- # Wrapped by mooring@grimoire on Wed Jul 29 11:34:09 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f '/home/grimoire/a/mooring/errlogger/bcast' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'/home/grimoire/a/mooring/errlogger/bcast'\"
- else
- echo shar: Extracting \"'/home/grimoire/a/mooring/errlogger/bcast'\" \(3210 characters\)
- sed "s/^X//" >'/home/grimoire/a/mooring/errlogger/bcast' <<'END_OF_FILE'
- X#!/usr/local/bin/perl -s
- X
- X$pat = 'S n C4 x8';
- X$inet = 2;
- X$echo = 7;
- X$smtp = 25;
- X$nntp = 119;
- X
- Xdie "Usage: $0 port \n" unless @ARGV;
- X$this = pack($pat,$inet,$ARGV[0], 0,0,0,0);
- X#$this = pack($pat,$inet,2345, 0,0,0,0);
- X
- Xsocket(LISTENER,2,1,6) || die "Socket $!\n";
- Xbind(LISTENER,$this) || die "Bind $!\n";
- Xlisten(LISTENER,5) || die "Listen $!\n";
- X
- X$readbits = $writebits = 8 x "\0";
- X# always read from standard input
- Xvec($readbits,0,1) = 1;
- X
- X# and look for new connections
- X#
- Xvec($readbits,fileno(LISTENER),1) = 1;
- X
- X$listener = fileno(LISTENER);
- X
- X$0 = $0;
- X#
- X# prototype file name
- X#
- X$sockp = 'clientaa';
- Xwhile (1)
- X{
- X $rbits = $readbits;
- X $wbits = $writebits;
- X grep(vec($wbits,$_,1) = 1, keys %bcastpending);
- X ($nfound, $timeleft) = select($rbits, $wbits, undef, undef);
- X if ($nfound > 0)
- X {
- X #
- X # we got a hit of some sort
- X # first see if anything to write
- X if ($wbits =~ /[^\0]/)
- X {
- X $bstr = unpack('b*',$wbits);
- X for($fd = index($bstr,'1'); $fd >= 0; $fd = index($bstr,'1',$fd+1))
- X {
- X # we just ignore errors here
- X #
- X $sock = $filenames[$fd];
- X send($sock,$bcastdata,0);
- X delete $bcastpending{$fd};
- X }
- X }
- X if ($rbits =~ /[^\0]/)
- X {
- X $bstr = unpack('b*',$rbits);
- X for($fd = index($bstr,'1'); $fd >= 0; $fd = index($bstr,'1',$fd+1))
- X {
- X if ($fd == 0)
- X {
- X # deal with stdin
- X $incount = sysread(STDIN,$bcastdata,1024);
- X if ($incount == 0)
- X {
- X # lost our connection
- X die "EOF from source\n";
- X }
- X elsif ($incount < 0)
- X {
- X # error
- X die "Error from source($!)\n" if ($! !~ /Interrupted/);
- X }
- X grep($bcastpending{$_} = 1, keys %active);
- X }
- X elsif ($fd == $listener)
- X {
- X # deal with cloning new socket
- X $newsock = $sockp++;
- X if ($addr = accept($newsock,LISTENER))
- X {
- X #
- X # see if we like this host
- X #
- X ($fam,$port,$inetaddr) = unpack('SSL',$addr);
- X if ($verbose)
- X {
- X $hostname = gethostbyaddr($addr, 2);
- X printf "Connection from $hostname %x %d\n", $inetaddr, $port;
- X }
- X # change inet address to match your site
- X if ($inetaddr != 0x7f000001 && $inetaddr & 0xffff0000 != 0x83920000)
- X {
- X #
- X # not a host we like, bounce it.
- X #
- X close ($newsock);
- X if ($verbose)
- X {
- X $hostname = gethostbyaddr($addr, 2);
- X printf "Connection refused from $hostname %x %d\n", $inetaddr, $port;
- X }
- X }
- X
- X #
- X # set bit vectors for later use
- X #
- X vec($readbits,fileno($newsock),1) = 1;
- X $bcastpending{fileno($newsock)} = 1 if length $bcastdata;
- X $active{fileno($newsock)} = 1;
- X $filenames[fileno($newsock)] = $newsock;
- X }
- X else
- X {
- X die "Error on accept $!\n";
- X }
- X }
- X else
- X {
- X # read data from socket and toss, check for eof
- X $sock = $filenames[$fd];
- X $incount = read($sock,$waste,1024);
- X if ($incount == 0)
- X {
- X # lost our connection
- X #
- X # reset bit vectors
- X #
- X vec($readbits,$fd,1) = 0;
- X $filenames[$fd] = '';
- X delete $bcastpending{$fd};
- X delete $active{$fd};
- X }
- X elsif ($incount < 0)
- X {
- X # error
- X die "Error from socket($!)\n" if ($! !~ /Interrupted/);
- X }
- X }
- X }
- X }
- X }
- X elsif ($nfound < 0)
- X {
- X die "Error ($!) on select\n" unless $! =~ /Interrupted/;
- X }
- X}
- Xexit 0;
- END_OF_FILE
- if test 3210 -ne `wc -c <'/home/grimoire/a/mooring/errlogger/bcast'`; then
- echo shar: \"'/home/grimoire/a/mooring/errlogger/bcast'\" unpacked with wrong size!
- fi
- chmod +x '/home/grimoire/a/mooring/errlogger/bcast'
- # end of '/home/grimoire/a/mooring/errlogger/bcast'
- fi
- if test -f '/home/grimoire/a/mooring/errlogger/bcast.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'/home/grimoire/a/mooring/errlogger/bcast.1'\"
- else
- echo shar: Extracting \"'/home/grimoire/a/mooring/errlogger/bcast.1'\" \(912 characters\)
- sed "s/^X//" >'/home/grimoire/a/mooring/errlogger/bcast.1' <<'END_OF_FILE'
- X.TH BCAST 1L
- X.SH NAME
- Xbcast \- broadcast daemon
- X.SH SYNOPSIS
- X.LP
- X.B bcast
- X[
- X.B \-verbose
- X]
- X.I port
- X.SH DESCRIPTION
- X.LP
- X.B bcast
- Xis a daemon that binds
- X.I port
- Xon the local machine and broadcasts whatever it receives on its
- Xstandard input to any processes that connect to it. This is done
- Xon a ``you snooze, you lose'' basis; that is, if a process hasn't read
- Xthe data that
- X.B bcast
- Xreceived before it gets another chunk,
- X.B bcast
- Xwill not attempt to buffer the old data. Any read done by that process
- Xwill get the most recently-received data.
- X.SH OPTIONS
- X.TP
- X.B \-verbose
- Xputs the program in verbose mode, causing it to print a message whenever
- Xa connection is accepted or rejected.
- X.SH DIAGNOSTICS
- X.LP
- XVarious error messages on system call failures.
- X.SH NOTES
- X.LP
- X.B bcast
- Xwill not accept connections from any machines outside
- Xof the Tymnet sub-network.
- X.SH AUTHOR
- X.LP
- XEd Mooring (mooring@antares.tymnet.com)
- END_OF_FILE
- if test 912 -ne `wc -c <'/home/grimoire/a/mooring/errlogger/bcast.1'`; then
- echo shar: \"'/home/grimoire/a/mooring/errlogger/bcast.1'\" unpacked with wrong size!
- fi
- # end of '/home/grimoire/a/mooring/errlogger/bcast.1'
- fi
- echo shar: End of shell archive.
- exit 0
-
- Regards,
- Ed Mooring (mooring@tymix.tymnet.com 408-922-7504)
-