I'm trying to write a simple server program using the usocket library that will perform a relatively trivial task - say, echoing data back. I want to make it able to do this with multiple clients, not having the single thread blocked while waiting for input from any single client. I've found that it's possible to check if a given socket has input ready using wait-for-input
with :timeout 0
. But I'm having a hard time getting read-sequence
to work how I want it to. If I give it an array with 50 elements, and only 5 are available, it will wait until 50 are available to put them in the array.
Is there any way to read blocks at a time (efficiently) with only a single thread without constantly having to wait for input? Or do I really have to just call read-byte
over and over until I've got everything?
The problem could be circumvented if there was some equivalent to read-sequence
that only read as much as was available at the time, or if there was some function that would tell me how many elements are ready to be read so I could size the array appropriately. But I don't know of either of those.
UPDATE: I'm specifically looking for binary solutions that don't require reading characters, so solutions involving read-char-no-hang
, listen
, etc won't help much unless they have a binary equivalent. I want to not work with characters because some character encodings, such as UTF-8, can have invalid sequences of bytes for which there is no character representation, and I want to be able to process any sequence of bytes. And I'm specifically looking for either solutions that don't require reading one byte at a time over and over, or confirmation that no such solution exists (in the standard), in which case I'd love to hear about the most convenient library that can provide the minimum necessary to accomplish that. It's not just that reading one byte at a time isn't the fastest way, it also requires whatever function I write to do that in a non-blocking manner to use usocket
's wait-for-input
function for every byte (since listen
doesn't work with byte streams), which would require the function to know about the socket and I would have to write an overly-specific read-all-bytes
function that wouldn't work with, say, File streams. It's possible, but I'm hoping there's a more general way.
Update: Realised this doesn't actually work on clisp - only tested on SBCL, where (listen) seems to do "what you might think" at least for network streams. Therefore this isn't a portable solution.. unless you replace the '(listen)' in the below loop to use some form of #+ features.
(listen) works perfectly fine with byte streams on sbcl. That should untie the Gordion knot here, and enable one to easily write something along the lines of: