in reply to Re: Serial I/O and time question
in thread Serial I/O and time question

Nice one. Didn't think of using select. :-)

sysread($fh, $c, 1);

However, for performance reasons (remember, sysread is not buffered) you should not read one byte at a time, but in chunks (up to 1024 bytes at a time, say).

Replies are listed 'Best First'.
Re: Re: Re: Serial I/O and time question
by shepner (Initiate) on Feb 21, 2004 at 21:12 UTC

    Here is my (curent) variation of the above gets function:

    sub gets { my $timeout; my($str, $c, $rin, $rout, $found, $timeleft); #be really pessimistic about how long it will take for the fist char $timeout = 120; #time in seconds $rin = ''; vec($rin, fileno(COM), 1) = 1; while (1) { ($found, $timeleft) = select($rout=$rin, undef, undef, $timeout); + #look for input for up to $timeout seconds last unless $found; #give up if nothing was found $timeout = $timeout - $timeleft; $timeout ||= 15; #the $timeout must be >= 15 seconds sysread(COM, $c, 1); #read the next char if (($c ne "\0")&&($c =~ /[\w\*\-\t\:\/ ]/)) { #sanitize the data $str .= $c; #put the char at the end of the string } elsif ($c =~ /\r/) { #Note: must only match \n OR \r. Matching +both does odd stuff last; } } return $str; }

    This version will hopefully take care of some of those *really* slow connections and not waste *too* much time after the transfer is complete.
    As for performance, Im not terribly concerned because the datastream is at 1200 baud and sofar this has proven fast enough. It also allows me to do some filtering of the data as it comes in.

Re: Re: Re: Serial I/O and time question
by duff (Parson) on Feb 24, 2004 at 22:28 UTC

    Aye. The actual code I pulled this from uses gets() in manner such that if the input matches a pattern, it returns immediately, so we read one character at a time to only read up to the point where the match occurs and nothing beyond.