network-programmingcommon-lispusocket

Usocket unsigned byte 8 doesn't receive data while character element type does


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).


Solution

  • 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).