ns_sockselect - Determine processable channels
ns_sockselect uses a select() call to determine which channels are readable, writable, or have exceptional conditions. ns_sockselect returns a list of three lists channels, readable, writable, exception channels. The -timeout option specifies the length of time to wait in seconds for ns_sockselect to return before timing out. The arguments rfds, wfds, efds are lists of channels for readable, writable, and exception channels.
# Start nonblocking connect()'s to www01 through # www09.foo.com and remember the read channelId which # corresponds to each write channelId. for {set n 1} {$n < 10} {incr n} { set host [format "www%2d.foo.com" $n] set fds [ns_sockopen -nonblock $host 80] set r [lindex $fds ] set w [lindex $fds 1] set w2r($w) $r lappend wfds $w } # All connect()'s are in progress, use select to wait for one or # more to become writable in the next two seconds which means # they may have connected. We're not interested in readable or # exception sockets so the corresponding lists are empty # (i.e., {}). set sel [ns_sockselect -timeout 2 {} $wfds {}] # Select returned - get the sockets ready to write to. set wfds [lindex $sel 1] # Use ns_sockcheck to see if the sockets actually connected and # didn't become writable because the connect() failed (e.g., no # Web server was running on port 80 on the corresponding machine). # Note that the wfds list may be empty, meaning all sockets timed # out on connect. set ok "" foreach w $wfds { if [ns_sockcheck $w] { # Socket is connected - send a GET HTTP request. lappend ok $w puts $w "GET /index.htm HTTP/1.0\r\n\r" # The flush is important, otherwise the remote # server may never see the data. flush $w } } # Get the read ids for each socket which we sent the GET request to. foreach w $ok { lappend rfds $w2r($w) } # Use select again to wait for the read sockets to have data # available in response to the GET request. set sel [ns_sockselect -timeout 2 $rfds {} {}] set rfds [lindex $sel 0] # Read the pages which came back. foreach r $rfds { if [ns_sockcheck $r] { set page($r) [read $r] } } # Close all the sockets foreach w [array names w2r] { close $w close $w2r($w) }