Is this socket code correct?

Lex Spoon lex at cc.gatech.edu
Wed Nov 24 00:02:15 UTC 1999


Juan Cires Martinez <jcm at mat.upm.es> wrote:
> > Do you get to choose the protocol?  If so, you might look at using
> > SimpleClientSocket, which has handy commands for sending/receiving a
> > line at a time, and for sending/receiving multi-line messages that
end
> > with a "." on a line by itself.  It will take care of all the
> > waitForData's, etc, for you.
> > 
> Thanks for the suggestion.  Unfortunately, the protocol is fixed (and
> binary).

Oh well.


> 
> > Otherwise, just remember that a read might return 0 bytes, so you
need
> > to program for it anyway.  It's not hard to do, you probably need to
do
> > it anyway, and it asks less of the networking primitives.
> 
> Yes, that's what I ended up doing:
> 
>   [socket dataAvailable] whileFalse: 
>     [(socket waitForDataUntil: Socket standardDeadline) ifFalse: 
>       [self error: 'Timeout reading reply']].
>   buffer _ ByteArray new: 10000.
>   read _ 0.
>   [(read < 4) and: [socket dataAvailable]]               "*"
>     whileTrue: [read _ socket receiveDataInto: buffer].  "*"
> 
>   read < 4
>     ifTrue: [self error: 'Too few data read'].
> 
> This seems to work, but I worry that I wont be able to detect a
time-out
> if it happens during the second loop (the one marked "*") since I can
> have socket dataAvailable being true and receiveDataInto: reading 0
> bytes.
> 
> Thanks, Juan.


You could wrap the loops together, and just remember to do a waitForData
before you readDataInto:.  Also, you need to deal with the case where
you read 1 byte on one iteration, and 3 bytes on the next--you probably
don't want to completely overwrite your buffer.  Here's a version that
should do what you want (though it's untested):

	read _ 0.
	[ read < 4 ] whileTrue: [
		socket waitForDataUntil: Socket standardDeadline.
		socket isConnected ifFalse: [ "deal with disconnects" ].
		read _ read + (socket readDataInto: aStringOrByteArray startingAt: read+1).
	].


To deal with timeouts, you probably need to compute the deadline up
front, instead of recomputing it each time you do a waitForData:

	timeoutTime _ Socket standardDeadline.  "calculate this up front"
	
	[ read < 4 and: [ Time millisecondClockValue < timeoutTime ] ] whileTrue: [
		socket waitForDataUntil: timeoutTime.
		"...otherwise as above..."
	].

	read < 4 ifTrue: [ "timeout occured" ].


Good luck with your robots.  It sounds fun!

Lex





More information about the Squeak-dev mailing list