I've run into some truly puzzling behavior with the USocket library. Consider the following snippet:
(defvar server-socket (usocket:socket-listen "localhost" 43593
:element-type
'(unsigned-byte 8)))
(defvar client-connection (usocket:socket-accept server-socket))
;in a separate terminal, type "telnet localhost 43593".
;then type some text and hit enter.
(listen (usocket:socket-stream client-connection))
=> NIL
Why is this happening? When I leave out :element-type '(unsigned-byte 8)
from the arguments to usocket:socket-listen
, it works just fine. I could understand if any arbitrary bytes couldn't be represented as characters (utf-8 encoding for example has invalid sequences of bytes), but the inverse - characters that can't be represented by bytes - makes no sense, especially in a network context.
(I'm running clisp-2.49 on Lubuntu 15.10, USocket 0.6.3.2, in case that helps).
Turns out the issue was in the precise wording used by the documentation for listen
in the hyperspec (http://www.lispworks.com/documentation/HyperSpec/Body/f_listen.htm).
Returns true if there is a character immediately available from input-stream; otherwise, returns false. On a non-interactive input-stream, listen returns true except when at end of file[1]. If an end of file is encountered, listen returns false. listen is intended to be used when input-stream obtains characters from an interactive device such as a keyboard.
Since the socket-stream
doesn't produce characters if it's told to produce '(unsigned-byte 8)
's, listen
will return NIL
for the stream regardless of whether it has data ready to be read.
As far as I know, there is no alternative to listen
for non-character types in the standard. Use usocket's wait-for-input
instead, with :timeout
set to 0 for polling (http://quickdocs.org/usocket/api).