[ Previous ] [ Contents ] [ Index ] [ Next ]

ns_sockselect

Overview

Determine readable file id's

Syntax

ns_sockselect ?-timeout seconds? rfds wfds efds

Description

ns_sockselect uses a select() call to determine which file id's re readable, writeable, or have exceptional conditions. ns_sockselect returns a list of three lists of: readable file id's, writeable file id's, and file id's with exceptions.

The -timeout option specifies the length of time to wait in seconds for ns_sockselect to return before timing out.

The rfds, wfds, and efds arguments are lists of readable file id's, writeable file id's, and file id's with exceptions, respectively.

Example

This example attempts to connect to nine servers at once and service the first available connections:

    # Start nonblocking connect()'s to user01 through 
#user09.blue.aol.com and remember the read fileid which 
    #cooresponds to each write fileid.
    for {set n 1} {$n < 10} {incr n} {
    	set host [format "user%2d.blue.aol.com" $n]
    	set fds [ns_sockopen -nonblock $host 80]
    	set r [lindex $fds 0]
    	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 cooresponding 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)
    }

Note that the close commands on Windows NT may not return until the non-blocking connect()'s actually complete, which could be several minutes later. A workaround is to schedule a close procedure to run once in a seperate thread which closes the files. For example:

    proc closelater {fds} {
    	foreach f $fds {
    		close $f
    	}
    }
    foreach w [array names w2r] {
    	lappend fds $w
    	lappend fds $w2r($w)
    }
    ns_schedule_proc -thread -once 1 "closelater $fds"

The ns_schedule_proc command will return immediately and the closelater procedure will take as long as necessary in it's own thread to complete. Note also that under the new linked interpreter architecture (see Linked Interpreters and Shared Files), the interpreter is owned by the new closeall thread so it won't affect other threads which need to evaluate tcl scripts.

Top of Page

[ Previous ] [ Contents ] [ Index ] [ Next ]
Copyright © 1996 America Online, Inc.