Article 12178 of comp.lang.perl:
Newsgroups: comp.lang.perl
Path: feenix.metronet.com!news.utdallas.edu!corpgate!bnrgate!bnr.co.uk!pipex!howland.reston.ans.net!cs.utexas.edu!csc.ti.com!tilde.csc.ti.com!cauldron!ra.csc.ti.com!enterprise!sunds
From: [email protected] (David M. Sundstrom)
Subject: Re: How to find if there's something on a Sock
Message-ID: <[email protected]>
Sender: [email protected]
Nntp-Posting-Host: enterprise.asic.sc.ti.com
Reply-To: [email protected]
Organization: Texas Instruments
References: <[email protected]>
Date: Thu, 31 Mar 1994 23:00:48 GMT
Lines: 83

In article [email protected], [email protected] (Andrew Smallbone) writes:
>
> Can anyone tell me how to find if there is something to read on a
> socket?
>
> I've been looking at:
>               select(RBITS,WBITS,EBITS,TIMEOUT)
> and           &FD_ISSET()  - from /usr/include/sys/types.h
>
> But I can't figure out how to create the structures correctly? Any Ideas?
>
> I've got a socket that I both read and (occasionally) write too and
> want to check when a message has been received without waiting on a
> read() until something comes in.  The messages haven't got newlines in
> so I can't do:
>       while (<Socket>) {
>               # process message code
>       };
>


Assuming your socket filehandle is called "SOCK", then:


   vec($rin,fileno(SOCKET),1) = 1;
   select($rout=$rin, undef, undef, $Timeout);
   $len=sysread(SOCKET,$buf,$buflen);

will block until something is there, unless you timeout.  You
can use a timeout of zero to check without blocking.  Use a timeout
of undef to wait forever.

The cool thing about select is that you can wait on more than
one thing, include other filehandles like STDIN:

  vec($rin1,fileno(SOCK1),1) = 1;
  vec($rin2,fileno(SOCK2),1) = 1;

  $rin = $rin1 | $rin2;

  for (;;) {

     select($rout=$rin, undef, undef, undef);


        if (vec($rout,fileno(SOCK1),1)) {

            ### do SOCK1 things

        }


        if (vec($rout,fileno(SOCK2),1)) {

            ### do SOCK2 things

        }
  }


Unbuffering your filehandles prior to using select will likely
be required:

 select((select(SOCK), $|=1)[$[]);

Which may be more clearly written as:

local($savehandle)=select(SOCK);
$|=1;  ## unbuffer SOCK
select($savehandle);  ## restore previously selected handle

Be certain not to mix sysread with other input mechanisms (such
as <SOCK> or read()).


-David