Socket.st
changeset 3467 24d35ef42e17
parent 3462 cfdc47761d0f
child 3481 b28077459fde
--- a/Socket.st	Sat Jan 24 00:02:47 2015 +0100
+++ b/Socket.st	Sat Jan 24 00:44:21 2015 +0100
@@ -255,412 +255,412 @@
 examples
 "
     example (get help info from an nntp server):
-                                                                        [exBegin]
-        |sock|
-
-        sock := Socket newTCPclientToHost:'smtp.exept.de' port:'smtp'.
-        sock isNil ifTrue:[
-            self warn:'no smtp daemon is running'.
-            ^ self
-        ].
-        Transcript showCR:sock nextLine.
-
-        sock nextPutAll:'HELO STX socket test'; cr.
-        Transcript showCR:sock nextLine.
-        sock close
-                                                                        [exEnd]
+									[exBegin]
+	|sock|
+
+	sock := Socket newTCPclientToHost:'smtp.exept.de' port:'smtp'.
+	sock isNil ifTrue:[
+	    self warn:'no smtp daemon is running'.
+	    ^ self
+	].
+	Transcript showCR:sock nextLine.
+
+	sock nextPutAll:'HELO STX socket test'; cr.
+	Transcript showCR:sock nextLine.
+	sock close
+									[exEnd]
 
 
     example (connect to finger daemon, get users entry):
-                                                                        [exBegin]
-        |sock entry|
-
-        sock := Socket newTCPclientToHost:'localhost' port:'finger'.
-        sock isNil ifTrue:[
-            self warn:'no finger daemon is running'.
-            ^ self
-        ].
-        sock useCRLF:true.
-        sock buffered:false.
-        sock isNil ifTrue:[
-            Transcript showCR:'cannot connect to local finger daemon'
-        ] ifFalse:[
-            sock nextPutAll:(OperatingSystem getLoginName).
-            sock cr.
-
-            entry := sock nextLine.
-            Transcript showCR:entry.
-
-            sock close
-        ]
-                                                                        [exEnd]
+									[exBegin]
+	|sock entry|
+
+	sock := Socket newTCPclientToHost:'localhost' port:'finger'.
+	sock isNil ifTrue:[
+	    self warn:'no finger daemon is running'.
+	    ^ self
+	].
+	sock useCRLF:true.
+	sock buffered:false.
+	sock isNil ifTrue:[
+	    Transcript showCR:'cannot connect to local finger daemon'
+	] ifFalse:[
+	    sock nextPutAll:(OperatingSystem getLoginName).
+	    sock cr.
+
+	    entry := sock nextLine.
+	    Transcript showCR:entry.
+
+	    sock close
+	]
+									[exEnd]
 
     example (connect to an ftp server):
-                                                                        [exBegin]
-        |sock|
-
-        sock := Socket newTCPclientToHost:'www.exept.de' port:'ftp'.
-
-        sock buffered:false.
-        Transcript showCR:sock nextLine.
-        sock nextPutAll:('USER ' , 'anonymous'); cr.
-        Transcript showCR:sock nextLine.
-        sock nextPutAll:('PASS ' , 'fooBar'); cr.
-        Transcript showCR:sock nextLine.
-        sock nextPutAll:'HELP'; cr.
-        [
-            |line|
-            line := sock nextLine.
-            Transcript showCR:line.
-            (line at:4) = $-
-        ] whileTrue.
-        sock close.
-
-        'dont know enough of the ftp protocol to continue here ...'
-                                                                        [exEnd]
+									[exBegin]
+	|sock|
+
+	sock := Socket newTCPclientToHost:'www.exept.de' port:'ftp'.
+
+	sock buffered:false.
+	Transcript showCR:sock nextLine.
+	sock nextPutAll:('USER ' , 'anonymous'); cr.
+	Transcript showCR:sock nextLine.
+	sock nextPutAll:('PASS ' , 'fooBar'); cr.
+	Transcript showCR:sock nextLine.
+	sock nextPutAll:'HELP'; cr.
+	[
+	    |line|
+	    line := sock nextLine.
+	    Transcript showCR:line.
+	    (line at:4) = $-
+	] whileTrue.
+	sock close.
+
+	'dont know enough of the ftp protocol to continue here ...'
+									[exEnd]
 
 
     example (connect to an snmp server [UDP]):
     Note: this is not a real connection, only the destination adress is
-          being fixed.
-                                                                        [exBegin]
-        |sock port|
-
-        sock := Socket newUDP.
-        port := Socket portOfService:'snmp'.
-        sock connectTo:'localhost' port:port.
-        sock buffered:false.
-        Transcript showCR:'got it'.
-        sock close.
-                                                                        [exEnd]
+	  being fixed.
+									[exBegin]
+	|sock port|
+
+	sock := Socket newUDP.
+	port := Socket portOfService:'snmp'.
+	sock connectTo:'localhost' port:port.
+	sock buffered:false.
+	Transcript showCR:'got it'.
+	sock close.
+									[exEnd]
 
 
     example (await connection from a client and read some data):
-                                                                        [exBegin]
-        |connectSock sock|
-
-        connectSock := Socket newTCPserverAtPort:9998.
-        connectSock isNil ifTrue:[
-            Transcript showCR:'socket setup failed.'.
-        ] ifFalse:[
-            Transcript showCR:'listen ..'.
-            (connectSock listenFor:5) ifFalse:[
-                Transcript showCR:'listen failed.'.
-            ] ifTrue:[
-                Transcript showCR:'wait'.
-                connectSock readWait.
-                Transcript showCR:'accept'.
-                sock := connectSock accept.
-                sock isNil ifTrue:[
-                    Transcript showCR:'accept failed.'.
-                ] ifFalse:[
-                    sock buffered:false.
-                    Transcript showCR:'server: got it'.
-                    'can now do transfer via sock'.
-                    Transcript showCR:'read'.
-                    Transcript showCR:('got: ' , sock nextLine).
-
-                    Transcript showCR:'close'.
-                    sock close
-                ].
-                connectSock close.
-            ]
-        ]
-                                                                        [exEnd]
+									[exBegin]
+	|connectSock sock|
+
+	connectSock := Socket newTCPserverAtPort:9998.
+	connectSock isNil ifTrue:[
+	    Transcript showCR:'socket setup failed.'.
+	] ifFalse:[
+	    Transcript showCR:'listen ..'.
+	    (connectSock listenFor:5) ifFalse:[
+		Transcript showCR:'listen failed.'.
+	    ] ifTrue:[
+		Transcript showCR:'wait'.
+		connectSock readWait.
+		Transcript showCR:'accept'.
+		sock := connectSock accept.
+		sock isNil ifTrue:[
+		    Transcript showCR:'accept failed.'.
+		] ifFalse:[
+		    sock buffered:false.
+		    Transcript showCR:'server: got it'.
+		    'can now do transfer via sock'.
+		    Transcript showCR:'read'.
+		    Transcript showCR:('got: ' , sock nextLine).
+
+		    Transcript showCR:'close'.
+		    sock close
+		].
+		connectSock close.
+	    ]
+	]
+									[exEnd]
 
 
     example (connect to above server and send some data):
-                                                                        [exBegin]
-        |sock|
-
-        sock := Socket newTCPclientToHost:'localhost' port:9998.
-        sock isNil ifTrue:[
-            Transcript showCR:'nope'
-        ] ifFalse:[
-            sock buffered:false.
-            Transcript showCR:'client: got it'.
-            'can now do transfer via sock'.
-            Transcript showCR:'sending <hello>'.
-            sock nextPutLine:'hello'.
-            sock close
-        ]
-                                                                        [exEnd]
+									[exBegin]
+	|sock|
+
+	sock := Socket newTCPclientToHost:'localhost' port:9998.
+	sock isNil ifTrue:[
+	    Transcript showCR:'nope'
+	] ifFalse:[
+	    sock buffered:false.
+	    Transcript showCR:'client: got it'.
+	    'can now do transfer via sock'.
+	    Transcript showCR:'sending <hello>'.
+	    sock nextPutLine:'hello'.
+	    sock close
+	]
+									[exEnd]
 
     example: UNIX domain socket (await connection from a client and read some data):
 
-        |connectSock sock|
-
-        '/tmp/ud_socket' asFilename remove.
-        connectSock := Socket newUNIXserverAt:'/tmp/ud_socket'.
-        connectSock isNil ifTrue:[
-            Transcript showCR:'socket setup failed.'.
-        ] ifFalse:[
-            Transcript showCR:'listen ..'.
-            (connectSock listenFor:5) ifFalse:[
-                Transcript showCR:'listen failed.'.
-            ] ifTrue:[
-                Transcript showCR:'wait'.
-                connectSock buffered:false.
-                connectSock readWait.
-                Transcript showCR:'accept'.
-                sock := connectSock accept.
-                sock isNil ifTrue:[
-                    Transcript showCR:'accept failed.'.
-                ] ifFalse:[
-                    sock buffered:false.
-                    Transcript showCR:'server: got it'.
-                    'can now do transfer via sock'.
-                    Transcript showCR:'read'.
-                    Transcript showCR:('got: ' , sock nextLine).
-
-                    Transcript showCR:'close'.
-                    sock close
-                ].
-                connectSock close.
-            ]
-        ]
+	|connectSock sock|
+
+	'/tmp/ud_socket' asFilename remove.
+	connectSock := Socket newUNIXserverAt:'/tmp/ud_socket'.
+	connectSock isNil ifTrue:[
+	    Transcript showCR:'socket setup failed.'.
+	] ifFalse:[
+	    Transcript showCR:'listen ..'.
+	    (connectSock listenFor:5) ifFalse:[
+		Transcript showCR:'listen failed.'.
+	    ] ifTrue:[
+		Transcript showCR:'wait'.
+		connectSock buffered:false.
+		connectSock readWait.
+		Transcript showCR:'accept'.
+		sock := connectSock accept.
+		sock isNil ifTrue:[
+		    Transcript showCR:'accept failed.'.
+		] ifFalse:[
+		    sock buffered:false.
+		    Transcript showCR:'server: got it'.
+		    'can now do transfer via sock'.
+		    Transcript showCR:'read'.
+		    Transcript showCR:('got: ' , sock nextLine).
+
+		    Transcript showCR:'close'.
+		    sock close
+		].
+		connectSock close.
+	    ]
+	]
 
 
     example (connect to above server and send some data;
-             Notice, this fails, if above server code is executed in the same ST/X image
-                     (at least on LINUX), since the OS does not correctly handle
-                     a connect from within an interrupted accept system call
-                     On SGI's SVR4, this works ok
-                                                                        [exBegin]
-        |sock|
-
-        sock := Socket newUNIXclientTo:'/tmp/ud_socket'.
-        sock isNil ifTrue:[
-            Transcript showCR:'nope'
-        ] ifFalse:[
-            sock buffered:false.
-            Transcript showCR:'client: got it'.
-            'can now do transfer via sock'.
-            Transcript showCR:'sending <hello>'.
-            sock nextPutLine:'hello'.
-            sock close
-        ]
-                                                                        [exEnd]
+	     Notice, this fails, if above server code is executed in the same ST/X image
+		     (at least on LINUX), since the OS does not correctly handle
+		     a connect from within an interrupted accept system call
+		     On SGI's SVR4, this works ok
+									[exBegin]
+	|sock|
+
+	sock := Socket newUNIXclientTo:'/tmp/ud_socket'.
+	sock isNil ifTrue:[
+	    Transcript showCR:'nope'
+	] ifFalse:[
+	    sock buffered:false.
+	    Transcript showCR:'client: got it'.
+	    'can now do transfer via sock'.
+	    Transcript showCR:'sending <hello>'.
+	    sock nextPutLine:'hello'.
+	    sock close
+	]
+									[exEnd]
 
 
     example (UDP await packet from a client and read some data):
-                                                                        [exBegin]
-        |udpSock sock addr n dataBuffer|
-
-        udpSock := Socket newUDPserverAtPort:9999.
-        udpSock isNil ifTrue:[
-            Transcript showCR:'socket setup failed.'.
-        ] ifFalse:[
-            Transcript showCR:'wait'.
-            udpSock readWait.
-
-            addr := IPSocketAddress new.
-            dataBuffer := ByteArray new:1000.
-            n := udpSock receiveFrom:addr buffer:dataBuffer start:1 for:dataBuffer size.
-            n > 0 ifTrue:[
-                Transcript showCR:('got: ' , n printString , 'bytes  from ' , addr printString).
-                Transcript showCR:('data: ' , (dataBuffer copyTo:n) printString).
-            ] ifFalse:[
-                Transcript showCR:'read failed'.
-            ].
-
-            Transcript showCR:'close'.
-            udpSock close
-        ]
-                                                                        [exEnd]
+									[exBegin]
+	|udpSock sock addr n dataBuffer|
+
+	udpSock := Socket newUDPserverAtPort:9999.
+	udpSock isNil ifTrue:[
+	    Transcript showCR:'socket setup failed.'.
+	] ifFalse:[
+	    Transcript showCR:'wait'.
+	    udpSock readWait.
+
+	    addr := IPSocketAddress new.
+	    dataBuffer := ByteArray new:1000.
+	    n := udpSock receiveFrom:addr buffer:dataBuffer start:1 for:dataBuffer size.
+	    n > 0 ifTrue:[
+		Transcript showCR:('got: ' , n printString , 'bytes  from ' , addr printString).
+		Transcript showCR:('data: ' , (dataBuffer copyTo:n) printString).
+	    ] ifFalse:[
+		Transcript showCR:'read failed'.
+	    ].
+
+	    Transcript showCR:'close'.
+	    udpSock close
+	]
+									[exEnd]
     example (connect to above UDP server and send some data;
-                                                                        [exBegin]
-        |sock|
-
-        sock := Socket newUDP.
-        sock isNil ifTrue:[
-            Transcript showCR:'nope'
-        ] ifFalse:[
-            sock sendTo:(IPSocketAddress new hostName:'localhost' port:9999) buffer:'hello world'.
-            sock close
-        ]
-                                                                        [exEnd]
+									[exBegin]
+	|sock|
+
+	sock := Socket newUDP.
+	sock isNil ifTrue:[
+	    Transcript showCR:'nope'
+	] ifFalse:[
+	    sock sendTo:(IPSocketAddress new hostName:'localhost' port:9999) buffer:'hello world'.
+	    sock close
+	]
+									[exEnd]
 
     example: pingWalk (try to ping hosts on the local network)
     Note: it dosen't use ICMP ping, but tries to reache the echo service,
-          which is disabled on most OS.
-                                                                        [exBegin]
-        |myAddress list top hosts walkProcess port|
-
-        myAddress := OperatingSystem getNetworkAddresses
-                        keysAndValuesSelect:[:eachIFName :eachAddress|
-                            eachAddress isLocal not
-                            and:[eachIFName = 'wlan0']
-                        ].
-        myAddress := myAddress first hostAddress.
-
-        port := Socket portOfService:'echo'.
-        port isNil ifTrue:[
-            self error:'dont know echo port'.
-            ^ self
-        ].
-
-        top := StandardSystemView new.
-        top label:'PING net walk'.
-
-        list := ScrollableView for:ListView in:top.
-        list origin:0.0@0.0 corner:1.0@1.0.
-
-        top openAndWait.
-
-        walkProcess := [
-            |l low hi direction tryHostID dottedName hostName conn addr|
-
-            l := SortedCollection new.
-
-            ' only works with type C-net
-              the code below could simply do 1 to:254 do:[:hostID }
-              but, to probe likely hosts earlier, the probing is done
-              ping-pong like around my ip-address (assuming, that other machines
-              have numbers around my own)'.
-
-            low := hi := (myAddress at:4).
-            direction := 1.
-
-            [low > 0 or:[hi < 255]] whileTrue:[
-                direction > 0 ifTrue:[
-                    hi := hi + 1.
-                    tryHostID := hi.
-                    direction := -1.
-                ] ifFalse:[
-                    low := low - 1.
-                    tryHostID := low.
-                    direction := 1.
-                ].
-                (tryHostID between:1 and:254) ifTrue:[
-                    dottedName := (myAddress at:1) printString
-                                  , '.' , (myAddress at:2) printString
-                                  , '.' , (myAddress at:3) printString
-                                  , '.' , tryHostID printString.
-
-                    top label:'PING net walk - trying ' , dottedName.
-
-                    top windowGroup withCursor:Cursor wait do:[
-                        conn := Socket newTCPclientToHost:dottedName port:port withTimeout:1000.
-                        conn notNil ifTrue:[
-                            addr := Socket ipAddressOfHost:dottedName.
-                            hostName := Socket hostWithIpAddress:addr.
-                            hostName isNil ifTrue:[
-                                hostName :='?'
-                            ].
-                            l add:(dottedName paddedTo:15 with:Character space)
-                                   , ' '
-                                   , (hostName paddedTo:15 with:Character space)
-                                   , ' up & reachable'.
-                            list list:l.
-                            conn close.
-                        ]
-                    ].
-                ].
-            ].
-            top label:'PING reachable hosts'.
-        ] forkAt:(Processor userBackgroundPriority).
-        walkProcess name:'ping net walker'.
-                                                                        [exEnd]
-
-
-        This example creates a simple UDP server that accepts
-        single packets from anybody and broadcasts them to all
-        clients that have connected so far.
-
-                                                                        [exBegin]
-        | socket address buffer msgSize clients |
-        clients := Set new.
-        address := IPSocketAddress new.
-        buffer := String new: 1024.
-
-        socket := self newUDPserverAtPort: 6666.
-
-        Transcript showCR: 'server starting'.
-
-        [
-            [true] whileTrue: [
-                (socket readWaitWithTimeoutMs: 200) ifFalse: [
-                    msgSize := socket
-                            receiveFrom: address
-                            buffer: buffer
-                            start: 1
-                            for: buffer size.
-
-                    clients add: address copy.
-                    clients do: [ :clientAddress |
-                            socket
-                                    sendTo: clientAddress
-                                    buffer: buffer
-                                    start: 1
-                                    for: msgSize]]
-            ]
-        ] ensure:[
-            Transcript showCR: 'server shutting down'.
-            socket close
-        ]
-                                                                        [exEnd]
+	  which is disabled on most OS.
+									[exBegin]
+	|myAddress list top hosts walkProcess port|
+
+	myAddress := OperatingSystem getNetworkAddresses
+			keysAndValuesSelect:[:eachIFName :eachAddress|
+			    eachAddress isLocal not
+			    and:[eachIFName = 'wlan0']
+			].
+	myAddress := myAddress first hostAddress.
+
+	port := Socket portOfService:'echo'.
+	port isNil ifTrue:[
+	    self error:'dont know echo port'.
+	    ^ self
+	].
+
+	top := StandardSystemView new.
+	top label:'PING net walk'.
+
+	list := ScrollableView for:ListView in:top.
+	list origin:0.0@0.0 corner:1.0@1.0.
+
+	top openAndWait.
+
+	walkProcess := [
+	    |l low hi direction tryHostID dottedName hostName conn addr|
+
+	    l := SortedCollection new.
+
+	    ' only works with type C-net
+	      the code below could simply do 1 to:254 do:[:hostID }
+	      but, to probe likely hosts earlier, the probing is done
+	      ping-pong like around my ip-address (assuming, that other machines
+	      have numbers around my own)'.
+
+	    low := hi := (myAddress at:4).
+	    direction := 1.
+
+	    [low > 0 or:[hi < 255]] whileTrue:[
+		direction > 0 ifTrue:[
+		    hi := hi + 1.
+		    tryHostID := hi.
+		    direction := -1.
+		] ifFalse:[
+		    low := low - 1.
+		    tryHostID := low.
+		    direction := 1.
+		].
+		(tryHostID between:1 and:254) ifTrue:[
+		    dottedName := (myAddress at:1) printString
+				  , '.' , (myAddress at:2) printString
+				  , '.' , (myAddress at:3) printString
+				  , '.' , tryHostID printString.
+
+		    top label:'PING net walk - trying ' , dottedName.
+
+		    top windowGroup withCursor:Cursor wait do:[
+			conn := Socket newTCPclientToHost:dottedName port:port withTimeout:1000.
+			conn notNil ifTrue:[
+			    addr := Socket ipAddressOfHost:dottedName.
+			    hostName := Socket hostWithIpAddress:addr.
+			    hostName isNil ifTrue:[
+				hostName :='?'
+			    ].
+			    l add:(dottedName paddedTo:15 with:Character space)
+				   , ' '
+				   , (hostName paddedTo:15 with:Character space)
+				   , ' up & reachable'.
+			    list list:l.
+			    conn close.
+			]
+		    ].
+		].
+	    ].
+	    top label:'PING reachable hosts'.
+	] forkAt:(Processor userBackgroundPriority).
+	walkProcess name:'ping net walker'.
+									[exEnd]
+
+
+	This example creates a simple UDP server that accepts
+	single packets from anybody and broadcasts them to all
+	clients that have connected so far.
+
+									[exBegin]
+	| socket address buffer msgSize clients |
+	clients := Set new.
+	address := IPSocketAddress new.
+	buffer := String new: 1024.
+
+	socket := self newUDPserverAtPort: 6666.
+
+	Transcript showCR: 'server starting'.
+
+	[
+	    [true] whileTrue: [
+		(socket readWaitWithTimeoutMs: 200) ifFalse: [
+		    msgSize := socket
+			    receiveFrom: address
+			    buffer: buffer
+			    start: 1
+			    for: buffer size.
+
+		    clients add: address copy.
+		    clients do: [ :clientAddress |
+			    socket
+				    sendTo: clientAddress
+				    buffer: buffer
+				    start: 1
+				    for: msgSize]]
+	    ]
+	] ensure:[
+	    Transcript showCR: 'server shutting down'.
+	    socket close
+	]
+									[exEnd]
 
    send a datagram to above server:
-                                                                        [exBegin]
-
-        | socket address buffer host msg |
-
-        host := Dialog
-                request: 'What is the name of the server''s host?'
-                initialAnswer: 'localhost'.
-
-        socket := self newUDP.
-
-        address := IPSocketAddress hostName: host port: 6666.
-
-        buffer := ByteArray new: 1000.
-        [
-            [(msg := Dialog request: 'Say something') isEmpty] whileFalse:[
-                | replySize stream |
-
-                socket writeWait.
-                stream := buffer writeStream.
-                stream nextPutAll: msg.
-                socket sendTo:address buffer:buffer start:1 for:stream position.
-                socket readWait.
-
-                replySize := socket receiveFrom:address buffer:buffer.
-                replySize > 0 ifTrue: [
-                    Transcript cr; nextPutAll: 'Server acknowledged: '.
-                    Transcript show: ((buffer copyFrom: 1 to: replySize) asString)
-                ]
-            ]
-        ] ensure: [socket close].
-        Transcript cr
-                                                                        [exEnd]
+									[exBegin]
+
+	| socket address buffer host msg |
+
+	host := Dialog
+		request: 'What is the name of the server''s host?'
+		initialAnswer: 'localhost'.
+
+	socket := self newUDP.
+
+	address := IPSocketAddress hostName: host port: 6666.
+
+	buffer := ByteArray new: 1000.
+	[
+	    [(msg := Dialog request: 'Say something') isEmpty] whileFalse:[
+		| replySize stream |
+
+		socket writeWait.
+		stream := buffer writeStream.
+		stream nextPutAll: msg.
+		socket sendTo:address buffer:buffer start:1 for:stream position.
+		socket readWait.
+
+		replySize := socket receiveFrom:address buffer:buffer.
+		replySize > 0 ifTrue: [
+		    Transcript cr; nextPutAll: 'Server acknowledged: '.
+		    Transcript show: ((buffer copyFrom: 1 to: replySize) asString)
+		]
+	    ]
+	] ensure: [socket close].
+	Transcript cr
+									[exEnd]
 
 
    loopBack:
-                                                                        [exBegin]
-
-        |readerTask readingSocket writingSocket|
-
-        readingSocket := self newTCPserverAtPort:9999.
-        readerTask :=
-            [
-                |connection|
-
-                readingSocket listenFor:1.
-                connection := readingSocket accept.
-                readingSocket close.
-                [connection atEnd] whileFalse:[
-                    Transcript showCR:(connection nextLine).
-                ].
-                connection close.
-            ] fork.
-
-        Delay waitForSeconds:1.
-        writingSocket := self newTCPclientToHost:'localhost' port:9999.
-        writingSocket nextPutLine:'Hello'.
-        writingSocket nextPutLine:'World'.
-        writingSocket close.
-                                                                        [exEnd]
+									[exBegin]
+
+	|readerTask readingSocket writingSocket|
+
+	readingSocket := self newTCPserverAtPort:9999.
+	readerTask :=
+	    [
+		|connection|
+
+		readingSocket listenFor:1.
+		connection := readingSocket accept.
+		readingSocket close.
+		[connection atEnd] whileFalse:[
+		    Transcript showCR:(connection nextLine).
+		].
+		connection close.
+	    ] fork.
+
+	Delay waitForSeconds:1.
+	writingSocket := self newTCPclientToHost:'localhost' port:9999.
+	writingSocket nextPutLine:'Hello'.
+	writingSocket nextPutLine:'World'.
+	writingSocket close.
+									[exEnd]
 "
 ! !
 
@@ -2783,46 +2783,46 @@
     int rslt;
 
     if (fp == nil) {
-        error = @symbol(errorNotOpen);
-        goto out;
+	error = @symbol(errorNotOpen);
+	goto out;
     }
 
     if (__INST(handleType) == @symbol(socketHandle)) {
-        SOCKET socket = SOCKET_FROM_FILE_OBJECT(fp);
-
-        if (@global(FileOpenTrace) == true) {
-            fprintf(stderr, "close socket [ExternalStream] %"_lx_"\n", socket);
-        }
-
-        // whether the close() will be successful or not - the handle is invalid now!
-        __INST(handle) = nil;
-        do {
+	SOCKET socket = SOCKET_FROM_FILE_OBJECT(fp);
+
+	if (@global(FileOpenTrace) == true) {
+	    fprintf(stderr, "close socket [ExternalStream] %"_lx_"\n", socket);
+	}
+
+	// whether the close() will be successful or not - the handle is invalid now!
+	__INST(handle) = nil;
+	do {
 #ifdef WIN32
-            rslt = __STX_WSA_NOINT_CALL1("closesocket", closesocket, socket);
+	    rslt = __STX_WSA_NOINT_CALL1("closesocket", closesocket, socket);
 #else
-            rslt = close(socket);
+	    rslt = close(socket);
 #endif
-        } while((rslt < 0) && (__threadErrno == EINTR));
-        if (rslt == 0) {
-            RETURN(self);
-        }
-        error = __mkSmallInteger(__threadErrno);
-    } 
+	} while((rslt < 0) && (__threadErrno == EINTR));
+	if (rslt == 0) {
+	    RETURN(self);
+	}
+	error = __mkSmallInteger(__threadErrno);
+    }
 
 out:;
 %}.
 
     error notNil ifTrue:[
-        error == #errorNotOpen ifTrue:[
-            self errorNotOpen.
-        ].
-        error isInteger ifTrue:[
-            lastErrorNumber := error.
-            self writeError:error.
-            ^ self.
-        ].
-        self primitiveFailed:error.
-        ^ self.
+	error == #errorNotOpen ifTrue:[
+	    self errorNotOpen.
+	].
+	error isInteger ifTrue:[
+	    lastErrorNumber := error.
+	    self writeError:error.
+	    ^ self.
+	].
+	self primitiveFailed:error.
+	^ self.
     ].
 
     super closeFile.
@@ -2831,8 +2831,8 @@
 
     fp := handle.
     fp notNil ifTrue:[
-        handle := nil.
-        self closeFile:fp
+	handle := nil.
+	self closeFile:fp
     ]
 ! !
 
@@ -2895,7 +2895,7 @@
     |serverSocketHandle addr domainClass newHandle|
 
     handle notNil ifTrue:[
-        ^ self errorAlreadyOpen
+	^ self errorAlreadyOpen
     ].
 
     domain := aServerSocket domain.
@@ -2903,12 +2903,12 @@
     handleType := aServerSocket handleType.
     serverSocketHandle := aServerSocket fileHandle.
     serverSocketHandle isNil ifTrue:[
-        ^ self error:'invalid server socket'
+	^ self error:'invalid server socket'
     ].
     "unix domain sockets do not return a valid peer name on accept"
     domainClass := self class socketAddressClassForDomain:domain.
     domainClass isNil ifTrue:[
-        ^ self error:'invalid (unsupported) domain'.
+	^ self error:'invalid (unsupported) domain'.
     ].
     addr := domainClass new.
     newHandle := OperatingSystem socketAccessor new.
@@ -2930,25 +2930,25 @@
 
 # if defined(O_NONBLOCK) && defined(SET_NDELAY)
     if (blocking == false) {
-        flags = fcntl(serverSocket, F_GETFL);
-        fcntl(serverSocket, F_SETFL, flags | O_NONBLOCK);
+	flags = fcntl(serverSocket, F_GETFL);
+	fcntl(serverSocket, F_SETFL, flags | O_NONBLOCK);
     }
 # endif
 
 # ifdef DO_WRAP_CALLS
     do {
-        __threadErrno = 0;
-        alen = sizeof(sa);
-        newSock = (SOCKET)STX_WSA_CALL3("accept", accept, serverSocket, &sa, &alen);
+	__threadErrno = 0;
+	alen = sizeof(sa);
+	newSock = (SOCKET)STX_WSA_CALL3("accept", accept, serverSocket, &sa, &alen);
     } while ((newSock < 0) && (__threadErrno == EINTR));
     if (newSock < 0) {
-        errno = __threadErrno;
+	errno = __threadErrno;
     }
 # else
     __BEGIN_INTERRUPTABLE__
     do {
-        alen = sizeof(sa);
-        newSock = accept(serverSocket, (struct sockaddr *) &sa, &alen);
+	alen = sizeof(sa);
+	newSock = accept(serverSocket, (struct sockaddr *) &sa, &alen);
     } while ((newSock < 0) && (errno == EINTR));
     __END_INTERRUPTABLE__
 # endif
@@ -2956,41 +2956,41 @@
 
 # if defined(O_NDELAY) && defined(SET_NDELAY)
     if (blocking == false) {
-        fcntl(serverSocket, F_SETFL, flags);
+	fcntl(serverSocket, F_SETFL, flags);
     }
 # endif
 
     if (newSock == -1) {
-        DBGPRINTF(("SOCKET: accept call failed errno=%d\n", errno));
-        __INST(lastErrorNumber) = __MKSMALLINT(errno);
-        RETURN (false);
+	DBGPRINTF(("SOCKET: accept call failed errno=%d\n", errno));
+	__INST(lastErrorNumber) = __MKSMALLINT(errno);
+	RETURN (false);
     }
 
     if (__isNonNilObject(addr)) {
-        OBJ oClass = __qClass(addr);
-        int nInstVars, nInstBytes, objSize;
-        char *addrP;
-
-        if (! __isBytes(addr) ) {
-            DBGPRINTF(("SOCKET: bad addr\n"));
-            closesocket(newSock);
-            RETURN (false);
-        }
-
-        nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
-        nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ));
-        objSize = __qSize(addr) - nInstBytes;
-        addrP = (char *)__InstPtr(addr) + nInstBytes;
-        if (objSize < alen) {
-            DBGPRINTF(("SOCKET: bad addr\n"));
-            closesocket(newSock);
-            RETURN (false);
-        }
-
-        /*
-         * extract the partners address
-         */
-        memcpy(addrP, (char *)&sa, alen);
+	OBJ oClass = __qClass(addr);
+	int nInstVars, nInstBytes, objSize;
+	char *addrP;
+
+	if (! __isBytes(addr) ) {
+	    DBGPRINTF(("SOCKET: bad addr\n"));
+	    closesocket(newSock);
+	    RETURN (false);
+	}
+
+	nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
+	nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ));
+	objSize = __qSize(addr) - nInstBytes;
+	addrP = (char *)__InstPtr(addr) + nInstBytes;
+	if (objSize < alen) {
+	    DBGPRINTF(("SOCKET: bad addr\n"));
+	    closesocket(newSock);
+	    RETURN (false);
+	}
+
+	/*
+	 * extract the partners address
+	 */
+	memcpy(addrP, (char *)&sa, alen);
     }
 
     /*
@@ -3008,19 +3008,19 @@
 # else // ! WIN32
     fp = fdopen(newSock, "r+");
     if (! fp) {
-        DBGPRINTF(("SOCKET: fdopen call failed\n"));
-        __INST(lastErrorNumber) = __MKSMALLINT(errno);
-        closesocket(newSock);
-        DBGFPRINTF((stderr, "SOCKET: close (fdopen failed) (%d)\n", newSock));
-        RETURN (false);
+	DBGPRINTF(("SOCKET: fdopen call failed\n"));
+	__INST(lastErrorNumber) = __MKSMALLINT(errno);
+	closesocket(newSock);
+	DBGFPRINTF((stderr, "SOCKET: close (fdopen failed) (%d)\n", newSock));
+	RETURN (false);
     }
 # endif // ! WIN32
 
     if ((@global(FileOpenTrace) == true) || __debugging__) {
 # ifdef WIN32
-        console_fprintf(stderr, "fdopen [Socket accept] -> fd: %d (H: %"_lx_")\n", _fd, (INT)newSock);
+	console_fprintf(stderr, "fdopen [Socket accept] -> fd: %d (H: %"_lx_")\n", _fd, (INT)newSock);
 # else
-        console_fprintf(stderr, "fdopen [Socket accept] -> %"_lx_" (fd: %d)\n", (INT)fp, newSock);
+	console_fprintf(stderr, "fdopen [Socket accept] -> %"_lx_" (fd: %d)\n", (INT)fp, newSock);
 # endif
     }
 
@@ -3049,7 +3049,7 @@
     |ok|
 
     handle isNil ifTrue:[
-        ^ self errorNotOpen
+	^ self errorNotOpen
     ].
 
 %{  /* STACK: 32000 */
@@ -3057,252 +3057,281 @@
     OBJ fp = __INST(handle);
 
     if (fp != nil) {
-        SOCKET sock = SOCKET_FROM_FILE_OBJECT(fp);
-        int opt = -1;
-        int level = -1;
-        int usize = -1;
-        int ret;
-        union u {
-            BOOL        u_bool;
-            int         u_int;
-            struct linger u_linger;
+	SOCKET sock = SOCKET_FROM_FILE_OBJECT(fp);
+	int opt = -1;
+	int level = -1;
+	int usize = -1;
+	int ret;
+	union u {
+	    BOOL        u_bool;
+	    int         u_int;
+	    struct linger  u_linger;
 # ifdef IP_ADD_MEMBERSHIP
-            struct ip_mreq      u_ip_mreq;
+	    struct ip_mreq u_ip_mreq;
 # endif
-        } u;
+# if defined(SO_RCVTIMEO) || defined(SO_SNDTIMEO)
+	    struct timeval u_tv;
+# endif
+
+
+	} u;
 
 # ifdef IP_ADD_MEMBERSHIP
-        if (option == @symbol(IP_DROP_MEMBERSHIP)) {
-            opt = IP_DROP_MEMBERSHIP;
-            goto dropOrAdd;
-        }
-        if (option == @symbol(IP_ADD_MEMBERSHIP)) {
-            /* add membership to a multicast group */
-            opt = IP_ADD_MEMBERSHIP;
+	if (option == @symbol(IP_DROP_MEMBERSHIP)) {
+	    opt = IP_DROP_MEMBERSHIP;
+	    goto dropOrAdd;
+	}
+	if (option == @symbol(IP_ADD_MEMBERSHIP)) {
+	    /* add membership to a multicast group */
+	    opt = IP_ADD_MEMBERSHIP;
 dropOrAdd:
-            level = IPPROTO_IP;
-            usize = sizeof(u.u_ip_mreq);
-            if (__isByteArrayLike(arg1) && __isByteArrayLike(arg2)) {
-                memcpy(&u.u_ip_mreq.imr_multiaddr, __byteArrayVal(arg1), sizeof(u.u_ip_mreq.imr_multiaddr));
-                memcpy(&u.u_ip_mreq.imr_interface, __byteArrayVal(arg2), sizeof(u.u_ip_mreq.imr_interface));
-            }
-            else
-                goto argError;
-        }
+	    level = IPPROTO_IP;
+	    usize = sizeof(u.u_ip_mreq);
+	    if (__isByteArrayLike(arg1) && __isByteArrayLike(arg2)) {
+		memcpy(&u.u_ip_mreq.imr_multiaddr, __byteArrayVal(arg1), sizeof(u.u_ip_mreq.imr_multiaddr));
+		memcpy(&u.u_ip_mreq.imr_interface, __byteArrayVal(arg2), sizeof(u.u_ip_mreq.imr_interface));
+	    }
+	    else
+		goto argError;
+	}
 # endif /* IP_ADD_MEMBERSHIP */
 
 # ifdef SO_BROADCAST
-        if (option == @symbol(SO_BROADCAST)) {
-            /* Enables transmission and receipt of broadcast messages on the socket. */
-            opt = SO_BROADCAST;
-            level = SOL_SOCKET;
-            usize = sizeof(u.u_bool);
-            if (arg1 == true) u.u_bool = TRUE;
-            else if (arg1 == false) u.u_bool = FALSE;
-            else goto argError;
-        }
+	if (option == @symbol(SO_BROADCAST)) {
+	    /* Enables transmission and receipt of broadcast messages on the socket. */
+	    opt = SO_BROADCAST;
+	    level = SOL_SOCKET;
+	    usize = sizeof(u.u_bool);
+	    if (arg1 == true) u.u_bool = TRUE;
+	    else if (arg1 == false) u.u_bool = FALSE;
+	    else goto argError;
+	}
 # endif /* SO_BROADCAST */
 
 # ifdef SO_CONDITIONAL
 #  if 0
-        if (option == @symbol(SO_CONDITIONAL)) {
-            /* Enables sockets to delay the acknowledgment of a connection until after the WSAAccept condition function is called. */
-            opt = SO_CONDITIONAL;
-            level = SOL_SOCKET;
-            usize = sizeof(u.u_bool);
-            if (arg1 == true) u.u_bool = TRUE;
-            else if (arg1 == false) u.u_bool = FALSE;
-            else goto argError;
-        }
+	if (option == @symbol(SO_CONDITIONAL)) {
+	    /* Enables sockets to delay the acknowledgment of a connection until after the WSAAccept condition function is called. */
+	    opt = SO_CONDITIONAL;
+	    level = SOL_SOCKET;
+	    usize = sizeof(u.u_bool);
+	    if (arg1 == true) u.u_bool = TRUE;
+	    else if (arg1 == false) u.u_bool = FALSE;
+	    else goto argError;
+	}
 #  endif
 # endif /* SO_CONDITIONAL */
 
 # ifdef SO_DEBUG
-        if (option == @symbol(SO_DEBUG)) {
-            /* Records debugging information. */
-            opt = SO_DEBUG;
-            level = SOL_SOCKET;
-            usize = sizeof(u.u_bool);
-            if (arg1 == true) u.u_bool = TRUE;
-            else if (arg1 == false) u.u_bool = FALSE;
-            else goto argError;
-        }
+	if (option == @symbol(SO_DEBUG)) {
+	    /* Records debugging information. */
+	    opt = SO_DEBUG;
+	    level = SOL_SOCKET;
+	    usize = sizeof(u.u_bool);
+	    if (arg1 == true) u.u_bool = TRUE;
+	    else if (arg1 == false) u.u_bool = FALSE;
+	    else goto argError;
+	}
 # endif /* SO_DEBUG */
 
 # ifdef SO_DONTLINGER
-        if (option == @symbol(SO_DONTLINGER)) {
-            /* Does not block close waiting for unsent data to be sent.
-               Setting this option is equivalent to setting SO_LINGER with l_onoff set to zero. */
-            opt = SO_DONTLINGER;
-            level = SOL_SOCKET;
-            usize = sizeof(u.u_bool);
-            if (arg1 == true) u.u_bool = TRUE;
-            else if (arg1 == false) u.u_bool = FALSE;
-            else goto argError;
-        }
+	if (option == @symbol(SO_DONTLINGER)) {
+	    /* Does not block close waiting for unsent data to be sent.
+	       Setting this option is equivalent to setting SO_LINGER with l_onoff set to zero. */
+	    opt = SO_DONTLINGER;
+	    level = SOL_SOCKET;
+	    usize = sizeof(u.u_bool);
+	    if (arg1 == true) u.u_bool = TRUE;
+	    else if (arg1 == false) u.u_bool = FALSE;
+	    else goto argError;
+	}
 # endif /* SO_DONTLINGER */
 
 # ifdef SO_DONTROUTE
-        if (option == @symbol(SO_DONTROUTE)) {
-            /* Does not route: sends directly to interface.
-               Succeeds but is ignored on AF_INET sockets;
-               fails on AF_INET6 sockets with WSAENOPROTOOPT.
-               Not supported on ATM sockets (results in an error). */
-            opt = SO_DONTROUTE;
-            level = SOL_SOCKET;
-            usize = sizeof(u.u_bool);
-            if (arg1 == true) u.u_bool = TRUE;
-            else if (arg1 == false) u.u_bool = FALSE;
-            else goto argError;
-        }
+	if (option == @symbol(SO_DONTROUTE)) {
+	    /* Does not route: sends directly to interface.
+	       Succeeds but is ignored on AF_INET sockets;
+	       fails on AF_INET6 sockets with WSAENOPROTOOPT.
+	       Not supported on ATM sockets (results in an error). */
+	    opt = SO_DONTROUTE;
+	    level = SOL_SOCKET;
+	    usize = sizeof(u.u_bool);
+	    if (arg1 == true) u.u_bool = TRUE;
+	    else if (arg1 == false) u.u_bool = FALSE;
+	    else goto argError;
+	}
 # endif /* SO_DONTROUTE */
 
 #if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
-        if (option == @symbol(TCP_NODELAY)) {
-            /* enable/disable TCP_NODELAY (i.e. disable/enable the Nagle algorithm) */
-            opt = TCP_NODELAY;
-            level = IPPROTO_TCP;
-            usize = sizeof(u.u_bool);
-            if (arg1 == true) u.u_bool = TRUE;
-            else if (arg1 == false) u.u_bool = FALSE;
-            else goto argError;
-        }
+	if (option == @symbol(TCP_NODELAY)) {
+	    /* enable/disable TCP_NODELAY (i.e. disable/enable the Nagle algorithm) */
+	    opt = TCP_NODELAY;
+	    level = IPPROTO_TCP;
+	    usize = sizeof(u.u_bool);
+	    if (arg1 == true) u.u_bool = TRUE;
+	    else if (arg1 == false) u.u_bool = FALSE;
+	    else goto argError;
+	}
 # endif /* TCP_NODELAY */
 
 # ifdef SO_KEEPALIVE
-        if (option == @symbol(SO_KEEPALIVE)) {
-            /* Sends keep-alives. Not supported on ATM sockets (results in an error). */
-            opt = SO_KEEPALIVE;
-            level = SOL_SOCKET;
-            usize = sizeof(u.u_bool);
-            if (arg1 == true) u.u_bool = TRUE;
-            else if (arg1 == false) u.u_bool = FALSE;
-            else goto argError;
-        }
+	if (option == @symbol(SO_KEEPALIVE)) {
+	    /* Sends keep-alives. Not supported on ATM sockets (results in an error). */
+	    opt = SO_KEEPALIVE;
+	    level = SOL_SOCKET;
+	    usize = sizeof(u.u_bool);
+	    if (arg1 == true) u.u_bool = TRUE;
+	    else if (arg1 == false) u.u_bool = FALSE;
+	    else goto argError;
+	}
 # endif /* SO_KEEPALIVE */
 
 # ifdef SO_LINGER
-        if (option == @symbol(SO_LINGER)) {
-            /* Lingers on close if unsent data is present. */
-            opt = SO_LINGER;
-            level = SOL_SOCKET;
-            usize = sizeof(u.u_linger);
-            if (arg1 == true) u.u_linger.l_onoff = TRUE;
-            else if (arg1 == false) u.u_linger.l_onoff = FALSE;
-            else goto argError;
-            if (arg2 == nil) u.u_linger.l_linger = 0;
-            else if (__isSmallInteger(arg2))u.u_linger.l_linger = __intVal(arg2);
-            else goto argError;
-            DBGPRINTF(("SOCKET: SO_LINGER %d %d\n", u.u_linger.l_onoff, u.u_linger.l_linger));
-        }
+	if (option == @symbol(SO_LINGER)) {
+	    /* Lingers on close if unsent data is present. */
+	    opt = SO_LINGER;
+	    level = SOL_SOCKET;
+	    usize = sizeof(u.u_linger);
+	    if (arg1 == true) u.u_linger.l_onoff = TRUE;
+	    else if (arg1 == false) u.u_linger.l_onoff = FALSE;
+	    else goto argError;
+	    if (arg2 == nil) u.u_linger.l_linger = 0;
+	    else if (__isSmallInteger(arg2))u.u_linger.l_linger = __intVal(arg2);
+	    else goto argError;
+	    DBGPRINTF(("SOCKET: SO_LINGER %d %d\n", u.u_linger.l_onoff, u.u_linger.l_linger));
+	}
 # endif /* SO_LINGER */
 
 # ifdef SO_OOBINLINE
-        if (option == @symbol(SO_OOBINLINE)) {
-            /* Receives OOB data in the normal data stream. */
-            opt = SO_OOBINLINE;
-            level = SOL_SOCKET;
-            usize = sizeof(u.u_bool);
-            if (arg1 == true) u.u_bool = TRUE;
-            else if (arg1 == false) u.u_bool = FALSE;
-            else goto argError;
-        }
+	if (option == @symbol(SO_OOBINLINE)) {
+	    /* Receives OOB data in the normal data stream. */
+	    opt = SO_OOBINLINE;
+	    level = SOL_SOCKET;
+	    usize = sizeof(u.u_bool);
+	    if (arg1 == true) u.u_bool = TRUE;
+	    else if (arg1 == false) u.u_bool = FALSE;
+	    else goto argError;
+	}
 # endif /* SO_OOBINLINE */
 
 # ifdef SO_RCVBUF
-        if (option == @symbol(SO_RCVBUF)) {
-            /* Specifies the total per-socket buffer space reserved for receives.
-               This is unrelated to SO_MAX_MSG_SIZE or the size of a TCP window. */
-            opt = SO_RCVBUF;
-            level = SOL_SOCKET;
-            usize = sizeof(u.u_int);
-            if (__isSmallInteger(arg1))u.u_int = __intVal(arg1);
-            else goto argError;
-        }
+	if (option == @symbol(SO_RCVBUF)) {
+	    /* Specifies the total per-socket buffer space reserved for receives.
+	       This is unrelated to SO_MAX_MSG_SIZE or the size of a TCP window. */
+	    opt = SO_RCVBUF;
+	    level = SOL_SOCKET;
+	    usize = sizeof(u.u_int);
+	    if (__isSmallInteger(arg1))u.u_int = __intVal(arg1);
+	    else goto argError;
+	}
 # endif /* SO_RCVBUF */
 
 # ifdef SO_SNDBUF
-        if (option == @symbol(SO_SNDBUF)) {
-            /* Specifies the total per-socket buffer space reserved for sends.
-               This is unrelated to SO_MAX_MSG_SIZE or the size of a TCP window. */
-            opt = SO_SNDBUF;
-            level = SOL_SOCKET;
-            usize = sizeof(u.u_int);
-            if (__isSmallInteger(arg1))u.u_int = __intVal(arg1);
-            else goto argError;
-        }
+	if (option == @symbol(SO_SNDBUF)) {
+	    /* Specifies the total per-socket buffer space reserved for sends.
+	       This is unrelated to SO_MAX_MSG_SIZE or the size of a TCP window. */
+	    opt = SO_SNDBUF;
+	    level = SOL_SOCKET;
+	    usize = sizeof(u.u_int);
+	    if (__isSmallInteger(arg1))u.u_int = __intVal(arg1);
+	    else goto argError;
+	}
 # endif /* SO_SNDBUF */
 
 # ifdef SO_REUSEADDR
-        if (option == @symbol(SO_REUSEADDR)) {
-            /* Allows the socket to be bound to an address that is already in use.  */
-            opt = SO_REUSEADDR;
-            level = SOL_SOCKET;
-            usize = sizeof(u.u_bool);
-            if (arg1 == true) u.u_bool = TRUE;
-            else if (arg1 == false) u.u_bool = FALSE;
-            else goto argError;
-        }
+	if (option == @symbol(SO_REUSEADDR)) {
+	    /* Allows the socket to be bound to an address that is already in use.  */
+	    opt = SO_REUSEADDR;
+	    level = SOL_SOCKET;
+	    usize = sizeof(u.u_bool);
+	    if (arg1 == true) u.u_bool = TRUE;
+	    else if (arg1 == false) u.u_bool = FALSE;
+	    else goto argError;
+	}
 # endif /* SO_OOBINLINE */
 
 # ifdef SO_EXCLUSIVEADDRUSE
-        if (option == @symbol(SO_EXCLUSIVEADDRUSE)) {
-            /* Enables a socket to be bound for exclusive access.
-               Does not require administrative privilege.  */
-            opt = SO_EXCLUSIVEADDRUSE;
-            level = SOL_SOCKET;
-            usize = sizeof(u.u_bool);
-            if (arg1 == true) u.u_bool = TRUE;
-            else if (arg1 == false) u.u_bool = FALSE;
-            else goto argError;
-        }
+	if (option == @symbol(SO_EXCLUSIVEADDRUSE)) {
+	    /* Enables a socket to be bound for exclusive access.
+	       Does not require administrative privilege.  */
+	    opt = SO_EXCLUSIVEADDRUSE;
+	    level = SOL_SOCKET;
+	    usize = sizeof(u.u_bool);
+	    if (arg1 == true) u.u_bool = TRUE;
+	    else if (arg1 == false) u.u_bool = FALSE;
+	    else goto argError;
+	}
 # endif /* SO_OOBINLINE */
 
-        if (usize == -1) goto argError;
-
-        ok = ( setsockopt( sock, level, opt, (char *)(&u), usize) >= 0) ? true : false;
+# ifdef SO_RCVTIMEO
+	if ((option == @symbol(SO_RCVTIMEO))
+	 && __isSmallInteger(arg1)
+	 && __isSmallInteger(arg2)) {
+	    opt = SO_RCVTIMEO;
+	    level = SOL_SOCKET;
+	    u.u_tv.tv_sec = __intVal(arg1);
+	    u.u_tv.tv_usec = __intVal(arg2);
+	    usize = sizeof(u.u_tv);
+	}
+# endif /* SO_RCVTIMEO */
+
+# ifdef SO_SNDTIMEO
+	if ((option == @symbol(SO_SNDTIMEO))
+	 && __isSmallInteger(arg1)
+	 && __isSmallInteger(arg2)) {
+	    opt = SO_SNDTIMEO;
+	    level = SOL_SOCKET;
+	    u.u_tv.tv_sec = __intVal(arg1);
+	    u.u_tv.tv_usec = __intVal(arg2);
+	    usize = sizeof(u.u_tv);
+	}
+# endif /* SO_SNDTIMEO */
+
+	if (usize == -1) goto argError;
+
+	ok = ( setsockopt( sock, level, opt, (char *)(&u), usize) >= 0) ? true : false;
     }
 argError: ;
 #endif /* NO_SOCKET */
 %}.
     ok isNil ifTrue:[
-        self primitiveFailed
+	self primitiveFailed
     ].
     ok ifFalse:[
-        'setsocketoption failed' infoPrintCR.
+	'setsocketoption failed' infoPrintCR.
     ].
 !
 
 shutdown:howNum
     "shutDown the socket - inform it that no more I/O will be performed.
-         0 - read side   (no further reads)
-             the tcp receive window is closed, so the peer cannot send more data.
-         1 - write side  (no further writes)
-             first, all queued data will be delivered to the peer.
-             Then, an orderly release (TCP FIN) is sent to signal the peer,
-             that we will not send more data.
-         2 - both read side and write side."
+	 0 - read side   (no further reads)
+	     the tcp receive window is closed, so the peer cannot send more data.
+	 1 - write side  (no further writes)
+	     first, all queued data will be delivered to the peer.
+	     Then, an orderly release (TCP FIN) is sent to signal the peer,
+	     that we will not send more data.
+	 2 - both read side and write side."
 
 %{
 #ifndef NO_SOCKET
     OBJ __handle = __INST(handle);
 
     if ((__handle != nil) && __isSmallInteger(howNum)) {
-        SOCKET sock = SOCKET_FROM_FILE_OBJECT(__handle);
-        INT how = __intVal(howNum);
-        INT ret;
+	SOCKET sock = SOCKET_FROM_FILE_OBJECT(__handle);
+	INT how = __intVal(howNum);
+	INT ret;
 
 # ifdef DO_WRAP_CALLS
-        do {
-            __threadErrno = 0;
-            DBGFPRINTF((stderr, "SOCKET: shutDown...\n"));
-            ret = (INT)STX_WSA_NOINT_CALL2("shutdown", shutdown, sock, how);
-            DBGFPRINTF((stderr, "SOCKET: shutDown -> %d (%d)\n", ret, __threadErrno));
-        } while ((ret < 0) && (__threadErrno == EINTR));
+	do {
+	    __threadErrno = 0;
+	    DBGFPRINTF((stderr, "SOCKET: shutDown...\n"));
+	    ret = (INT)STX_WSA_NOINT_CALL2("shutdown", shutdown, sock, how);
+	    DBGFPRINTF((stderr, "SOCKET: shutDown -> %d (%d)\n", ret, __threadErrno));
+	} while ((ret < 0) && (__threadErrno == EINTR));
 # else
-        __BEGIN_INTERRUPTABLE__
-        shutdown(sock, how);
-        __END_INTERRUPTABLE__
+	__BEGIN_INTERRUPTABLE__
+	shutdown(sock, how);
+	__END_INTERRUPTABLE__
 # endif
     }
 #endif
@@ -3568,7 +3597,7 @@
     |domainName domainCode typeCode error newHandle|
 
     handle notNil ifTrue:[
-        ^ self errorAlreadyOpen
+	^ self errorAlreadyOpen
     ].
     domainName := SocketAddress domainCodeFromName:domainArg.
     domainCode := OperatingSystem domainCodeOf:domainName.
@@ -3590,19 +3619,19 @@
 # endif
 
     if (! __isSmallInteger(domainCode)) {
-        error = @symbol(badArgument1);
-        goto out;
+	error = @symbol(badArgument1);
+	goto out;
     }
     if (! __isSmallInteger(typeCode)) {
-        error = @symbol(badArgument2);
-        goto out;
+	error = @symbol(badArgument2);
+	goto out;
     }
     if (protocolNumber != nil) {
-        if (!__isSmallInteger(protocolNumber)) {
-            error = @symbol(badArgument3);
-            goto out;
-        }
-        proto = __intVal(protocolNumber);
+	if (!__isSmallInteger(protocolNumber)) {
+	    error = @symbol(badArgument3);
+	    goto out;
+	}
+	proto = __intVal(protocolNumber);
     }
 
     /*
@@ -3614,91 +3643,91 @@
 # ifdef WIN32
     sock = WSASocket(dom, typ, proto, 0, 0, noInheritFlag);
     if (sock == INVALID_SOCKET && noInheritFlag) {
-        // tried to open socket with WSA_FLAG_NO_HANDLE_INHERIT
-        // This fails on older windows versions, e.g. Windows XP
-        sock = WSASocket(dom, typ, proto, 0, 0, 0);
-        if (sock != INVALID_SOCKET) {
-            // no error without WSA_FLAG_NO_HANDLE_INHERIT,
-            // never use this flag again!
-            noInheritFlag = 0;
-        }
+	// tried to open socket with WSA_FLAG_NO_HANDLE_INHERIT
+	// This fails on older windows versions, e.g. Windows XP
+	sock = WSASocket(dom, typ, proto, 0, 0, 0);
+	if (sock != INVALID_SOCKET) {
+	    // no error without WSA_FLAG_NO_HANDLE_INHERIT,
+	    // never use this flag again!
+	    noInheritFlag = 0;
+	}
     }
     if (sock == INVALID_SOCKET) {
-        errno = WSAGetLastError();
+	errno = WSAGetLastError();
 
 # else  // !WIN32
 
     sock = socket(dom, typ, proto);
 # if defined(EPROTONOSUPPORT) /* for SGI */
     if ((sock < 0) && (proto != 0) && (errno == EPROTONOSUPPORT)) {
-        DBGPRINTF(("SOCKET: retry with UNSPEC protocol\n"));
-        proto = 0;
-        sock = socket(dom, typ, 0);
+	DBGPRINTF(("SOCKET: retry with UNSPEC protocol\n"));
+	proto = 0;
+	sock = socket(dom, typ, 0);
     }
 # endif
     if (sock < 0) {
 # endif // !WIN32
 
-        DBGPRINTF(("SOCKET: socket(dom=%d typ=%d proto=%d) call failed errno=%d\n", dom, typ, proto, errno));
-        error = __MKSMALLINT(errno);
+	DBGPRINTF(("SOCKET: socket(dom=%d typ=%d proto=%d) call failed errno=%d\n", dom, typ, proto, errno));
+	error = __MKSMALLINT(errno);
     } else {
 # if defined(SET_LINGER_WHEN_CREATING_SOCKET) && defined(SO_LINGER)
-        {
-            struct linger l;
-
-            l.l_onoff = 1;
-            l.l_linger = 30;
-            setsockopt( sock, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
-        }
+	{
+	    struct linger l;
+
+	    l.l_onoff = 1;
+	    l.l_linger = 30;
+	    setsockopt( sock, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
+	}
 # endif
 # ifdef WIN32
-        /*
-         * make it blocking
-         */
-        {
-            unsigned long zero = 0;
-            ioctlsocket(sock, FIONBIO, &zero);
-        }
-        {
+	/*
+	 * make it blocking
+	 */
+	{
+	    unsigned long zero = 0;
+	    ioctlsocket(sock, FIONBIO, &zero);
+	}
+	{
 #  if 0 && (defined( __BORLANDC__ ) || defined( __MINGW__ ))
-            /*
-             * make it a FILE *
-             */
-            __stxWrapApiEnterCritical();
-            _fd = _open_osfhandle((long)sock, 0);
-            __stxWrapApiLeaveCritical();
+	    /*
+	     * make it a FILE *
+	     */
+	    __stxWrapApiEnterCritical();
+	    _fd = _open_osfhandle((long)sock, 0);
+	    __stxWrapApiLeaveCritical();
 #  else
-            _fd = (int)sock;
+	    _fd = (int)sock;
 #  endif
-            DBGPRINTF(("SOCKET: sock=%d fd=%d\n", sock, _fd));
-        }
+	    DBGPRINTF(("SOCKET: sock=%d fd=%d\n", sock, _fd));
+	}
 # else  // !WIN32
-        fp = fdopen(sock, "r+");
-        if (! fp) {
-            DBGPRINTF(("SOCKET: fdopen call failed\n"));
-            error = __MKSMALLINT(errno);
-            __BEGIN_INTERRUPTABLE__
-            closesocket(sock);
-            DBGFPRINTF((stderr, "SOCKET: fdopen failed (%d)\n", sock));
-            __END_INTERRUPTABLE__
-            goto out;
-        }
+	fp = fdopen(sock, "r+");
+	if (! fp) {
+	    DBGPRINTF(("SOCKET: fdopen call failed\n"));
+	    error = __MKSMALLINT(errno);
+	    __BEGIN_INTERRUPTABLE__
+	    closesocket(sock);
+	    DBGFPRINTF((stderr, "SOCKET: fdopen failed (%d)\n", sock));
+	    __END_INTERRUPTABLE__
+	    goto out;
+	}
 # endif // !WIN32
 
-        if (@global(FileOpenTrace) == true) {
+	if (@global(FileOpenTrace) == true) {
 # ifdef WIN32
-            console_fprintf(stderr, "fdopen [Socket create] -> fd: %d (H: %"_lx_")\n", (INT)_fd, (INT)sock);
+	    console_fprintf(stderr, "fdopen [Socket create] -> fd: %d (H: %"_lx_")\n", (INT)_fd, (INT)sock);
 # else
-            console_fprintf(stderr, "fdopen [Socket] -> %"_lx_" (fd: %d)\n", (INT)fp, sock);
+	    console_fprintf(stderr, "fdopen [Socket] -> %"_lx_" (fd: %d)\n", (INT)fp, sock);
 # endif
-        }
+	}
 
 # ifdef WIN32
-        __externalAddressVal(newHandle) = _fd;
-        __INST(handleType) = @symbol(socketHandle);
+	__externalAddressVal(newHandle) = _fd;
+	__INST(handleType) = @symbol(socketHandle);
 # else
-        __externalAddressVal(newHandle) = fp;
-        __INST(handleType) = @symbol(socketFilePointer);
+	__externalAddressVal(newHandle) = fp;
+	__INST(handleType) = @symbol(socketFilePointer);
 # endif
     }
 #endif
@@ -3707,15 +3736,15 @@
 
     "all ok?"
     handleType notNil ifTrue:[
-        handle := newHandle.
-        domain := domainArg.
-        socketType := typeArg.
-        Lobby register:self.
-        ^ self.
+	handle := newHandle.
+	domain := domainArg.
+	socketType := typeArg.
+	Lobby register:self.
+	^ self.
     ].
     error isInteger ifTrue:[
-        lastErrorNumber := error.
-        ^ self openError:error.
+	lastErrorNumber := error.
+	^ self openError:error.
     ].
     ^ self primitiveFailed:error.
 
@@ -3727,19 +3756,19 @@
 
 !Socket methodsFor:'specials'!
 
-linger:anIntegerOrNil 
+linger:anIntegerOrNil
     "set the linger behavior on close:
       anIntegerOrNil == nil: close returns immediately, socket tries
-                             to send buffered data in background.
+			     to send buffered data in background.
       anIntegerOrNil == 0:   close returns immediately, bufferd data is discarded.
       anIntegerOrNil > 0:    close waits this many seconds for buffered data
-                             to be delivered, after this time buffered data is
-                             discarded and close returns"
-    
-    ^ self 
-        setSocketOption:#'SO_LINGER'
-        argument:anIntegerOrNil notNil
-        argument:anIntegerOrNil.
+			     to be delivered, after this time buffered data is
+			     discarded and close returns"
+
+    ^ self
+	setSocketOption:#'SO_LINGER'
+	argument:anIntegerOrNil notNil
+	argument:anIntegerOrNil.
 !
 
 receiveBufferSize
@@ -3802,7 +3831,7 @@
     |millis|
 
     handle isNil ifTrue:[
-        ^ self errorNotOpen
+	^ self errorNotOpen
     ].
 %{
 #if defined(SO_RCVTIMEO) && defined(SOL_SOCKET)
@@ -3814,13 +3843,13 @@
 
     len = sizeof(struct timeval);
     if (getsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, &len) == 0) {
-        __millis = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
-        millis = __mkSmallInteger(__millis);
+	__millis = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+	millis = __mkSmallInteger(__millis);
 # if 0
-        console_fprintf(stderr, "getsockopt -> s:%d us:%d -> millis:%d\n", tv.tv_sec, tv.tv_usec, __millis);
+	console_fprintf(stderr, "getsockopt -> s:%d us:%d -> millis:%d\n", tv.tv_sec, tv.tv_usec, __millis);
 # endif
     } else {
-        console_fprintf(stderr, "Socket [warning]: getsockopt %d failed; errno=%d\n", sock, errno);
+	console_fprintf(stderr, "Socket [warning]: getsockopt %d failed; errno=%d\n", sock, errno);
     }
 #endif
 %}.
@@ -3836,26 +3865,26 @@
     |millis|
 
     handle isNil ifTrue:[
-        ^ self errorNotOpen
+	^ self errorNotOpen
     ].
     millis := (seconds * 1000) rounded.
 %{
 #if defined(SO_RCVTIMEO) && defined(SOL_SOCKET)
     if (__isSmallInteger(millis)) {
-        OBJ fp = __INST(handle);
-        SOCKET sock = SOCKET_FROM_FILE_OBJECT(fp);
-        int __millis = __intVal(millis);
-        struct timeval tv = {0, 0};
-
-        tv.tv_sec = __millis / 1000;
-        tv.tv_usec = (__millis % 1000) * 1000;
+	OBJ fp = __INST(handle);
+	SOCKET sock = SOCKET_FROM_FILE_OBJECT(fp);
+	int __millis = __intVal(millis);
+	struct timeval tv = {0, 0};
+
+	tv.tv_sec = __millis / 1000;
+	tv.tv_usec = (__millis % 1000) * 1000;
 # if 0
-        console_fprintf(stderr, "setsockopt -> millis:%d -> s:%d us:%d \n", __millis, tv.tv_sec, tv.tv_usec);
+	console_fprintf(stderr, "setsockopt -> millis:%d -> s:%d us:%d \n", __millis, tv.tv_sec, tv.tv_usec);
 # endif
-        if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(struct timeval)) == 0) {
-            RETURN(true);
-        }
-        console_fprintf(stderr, "Socket [warning]: setsockopt %d failed; errno=%d\n", sock, errno);
+	if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(struct timeval)) == 0) {
+	    RETURN(true);
+	}
+	console_fprintf(stderr, "Socket [warning]: setsockopt %d failed; errno=%d\n", sock, errno);
     }
 #endif
 %}.
@@ -3922,7 +3951,7 @@
     |millis|
 
     handle isNil ifTrue:[
-        ^ self errorNotOpen
+	^ self errorNotOpen
     ].
 %{
 #if defined(SO_SNDTIMEO) && defined(SOL_SOCKET)
@@ -3934,13 +3963,13 @@
 
     len = sizeof(struct timeval);
     if (getsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv, &len) == 0) {
-        __millis = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
-        millis = __mkSmallInteger(__millis);
+	__millis = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+	millis = __mkSmallInteger(__millis);
 # if 0
-        console_fprintf(stderr, "getsockopt -> s:%d us:%d -> millis:%d\n", tv.tv_sec, tv.tv_usec, __millis);
+	console_fprintf(stderr, "getsockopt -> s:%d us:%d -> millis:%d\n", tv.tv_sec, tv.tv_usec, __millis);
 # endif
     } else {
-        console_fprintf(stderr, "Socket [warning]: getsockopt %d failed; errno=%d\n", sock, errno);
+	console_fprintf(stderr, "Socket [warning]: getsockopt %d failed; errno=%d\n", sock, errno);
     }
 #endif
 %}.
@@ -3956,26 +3985,26 @@
     |millis|
 
     handle isNil ifTrue:[
-        ^ self errorNotOpen
+	^ self errorNotOpen
     ].
     millis := (seconds * 1000) rounded.
 %{
 #if defined(SO_SNDTIMEO) && defined(SOL_SOCKET)
     if (__isSmallInteger(millis)) {
-        OBJ fp = __INST(handle);
-        SOCKET sock = SOCKET_FROM_FILE_OBJECT(fp);
-        int __millis = __intVal(millis);
-        struct timeval tv = {0, 0};
-
-        tv.tv_sec = __millis / 1000;
-        tv.tv_usec = (__millis % 1000) * 1000;
+	OBJ fp = __INST(handle);
+	SOCKET sock = SOCKET_FROM_FILE_OBJECT(fp);
+	int __millis = __intVal(millis);
+	struct timeval tv = {0, 0};
+
+	tv.tv_sec = __millis / 1000;
+	tv.tv_usec = (__millis % 1000) * 1000;
 # if 0
-        console_fprintf(stderr, "setsockopt -> millis:%d -> s:%d us:%d \n", __millis, tv.tv_sec, tv.tv_usec);
+	console_fprintf(stderr, "setsockopt -> millis:%d -> s:%d us:%d \n", __millis, tv.tv_sec, tv.tv_usec);
 # endif
-        if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv, sizeof(struct timeval)) == 0) {
-            RETURN(true);
-        }
-        console_fprintf(stderr, "Socket [warning]: setsockopt %d failed; errno=%d\n", sock, errno);
+	if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv, sizeof(struct timeval)) == 0) {
+	    RETURN(true);
+	}
+	console_fprintf(stderr, "Socket [warning]: setsockopt %d failed; errno=%d\n", sock, errno);
     }
 #endif
 %}.
@@ -4017,41 +4046,41 @@
 
     "first, a quick check if data is already available"
     self canReadWithoutBlocking ifTrue:[
-        ^ self accept.
+	^ self accept.
     ].
     otherConnections do:[:aConnection |
-        aConnection canReadWithoutBlocking ifTrue:[
-            ^ aConnection
-        ]
+	aConnection canReadWithoutBlocking ifTrue:[
+	    ^ aConnection
+	]
     ].
 
     "check again - prevent incoming interrupts from disturbing our setup"
     wasBlocked := OperatingSystem blockInterrupts.
     [
-        sema := Semaphore new name:'multiReadWait'.
-        otherConnections do:[:aConnection |
-            Processor signal:sema onInput:(aConnection fileDescriptor).
-        ].
-        Processor signal:sema onInput:(self fileDescriptor).
-        timeoutSeconds notNil ifTrue:[
-            Processor signal:sema afterSeconds:timeoutSeconds
-        ].
-        Processor activeProcess state:#ioWait.
-        sema wait.
+	sema := Semaphore new name:'multiReadWait'.
+	otherConnections do:[:aConnection |
+	    Processor signal:sema onInput:(aConnection fileDescriptor).
+	].
+	Processor signal:sema onInput:(self fileDescriptor).
+	timeoutSeconds notNil ifTrue:[
+	    Processor signal:sema afterSeconds:timeoutSeconds
+	].
+	Processor activeProcess state:#ioWait.
+	sema wait.
     ] ifCurtailed:[
-        sema notNil ifTrue:[Processor disableSemaphore:sema].
-        wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+	sema notNil ifTrue:[Processor disableSemaphore:sema].
+	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
     ].
     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
 
     "see who it was ..."
     self canReadWithoutBlocking ifTrue:[
-        ^ self accept.
+	^ self accept.
     ].
     otherConnections do:[:aConnection |
-        aConnection canReadWithoutBlocking ifTrue:[
-            ^ aConnection
-        ]
+	aConnection canReadWithoutBlocking ifTrue:[
+	    ^ aConnection
+	]
     ].
 
     "none - a timeout"
@@ -4076,10 +4105,9 @@
 !Socket class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.306 2014-12-31 09:11:03 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.307 2015-01-23 23:44:21 cg Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.306 2014-12-31 09:11:03 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.307 2015-01-23 23:44:21 cg Exp $'
 ! !
-