A TCP stream wraps a socket, which is returned by tcp-connect:
(let ((socket (tcp-connect "google.com" 80 ... :dont-drain-read-buffer t)))
(make-instance 'async-io-stream :socket socket))
tcp-connect
makes this a bit more convenient as well:
(tcp-connect "google.com" 80 ... :stream t)
The stream we just created is a normal lisp stream which can be operated on via close
, read-sequence
, write-sequence
, etc. One caveat is that the stream does not block when pulling data from it, so reading from the stream should be triggered by the read-cb
given to tcp-connect
.
See the notes on buffer draining section for an explanation of the :dont-drain-read-buffer
parameter.
The base async stream, extended by all other cl-async TCP streams.
async-output-streamThe base output stream, can only be used to send data on a socket.
async-input-streamThe base input stream, can only be used to recieve data on a socket.
async-io-streamExtends both async-output-stream
and async-input-stream
, and allows both reading and writing on the underlying socket.
Streams work by sucking the data out of the socket they are set up to wrap. Normally, when a read-cb
fires on a socket, cl-async will drain the data received and put it into a byte array it passes to the read-cb
.
In the case of streams, cl-async pushes the data onto the stream’s input buffer instead of passing the data to the read-cb
directly. The stream is then passed as the second parameter to the read-cb
(the first still being the socket object). This is what :dont-drain-read-buffer
does for you. Note that if you specify :stream t
then dont-drain-read-buffer
is assumed to be T
unless explicitely stated otherwise.
When the read-cb
fires and dont-drain-read-buffer
is T
, the data
param will always be the stream and the socket data can be read via read-sequence
or similar. Note that the socket arg (the first arg) to the read-cb
is still a socket.
(tcp-connect "musio.com" 80
(lambda (sock stream)
(let* ((seq (make-array 4096 :element-type '(unsigned-byte 8)))
(num-bytes (read-sequence seq stream :end 4096)))
(format t "~a" (babel:octets-to-string (subseq seq 0 num-bytes)))))
(lambda (ev) (format t "ev: ~a~%" ev))
:data (format nil "GET /~C~C" #\return #\newline)
:stream t
:read-timeout 5)
Note that you can write the socket returned by (tcp-connect ... :stream t)
with write-sequence
like any other stream.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4