One of :input
, :output
, or :io
.
One of base-char
, (signed-byte 8)
and (unsigned-byte 8)
.
A positive number or nil
.
A positive number or nil
.
A keyword, t
or nil
, or a foreign pointer of type ssl-ctx-pointer or ssl-pointer.
One of the keywords :client
, :server
or :both
. The default value is :server
.
The class socket-stream
implements a buffered stream connected to a socket. The socket handle, specified by :socket
, and the direction, specified by :direction
, must be passed for a meaningful stream to be constructed. Common Lisp input functions such as read-char
will see end-of-file
if the other end of the socket is closed.
The :element-type
initarg determines the expected element type of the stream traffic. However, stream input and output functions for character and binary data generally work in the obvious way on a socket-stream
with any of the allowed values of element-type. For example, read-sequence
can be called with a string buffer and a binary socket-stream
: the character data is constructed from the input as if by code-char
. Similarly write-sequence
can be called with a string buffer and a binary socket-stream
: the output is converted from the character data as if by char-code
. Also, 8-bit binary data can be read and written to a base-char
socket-stream
.
All standard stream I/O functions except for write-byte
and read-byte
have this flexibility.
The :read-timeout
initarg specifies the read timeout in seconds, or is nil
, meaning there are no timeouts during reads (this is the default).
The read-timeout property is intended for use when a socket connection might hang during a call to any Common Lisp input function. The read-timeout can be set by make-instance or by open-tcp-stream. It can also be modified by (setf stream:stream-read-timeout)
. When read-timeout is nil
, there is no timeout during reads and the call may hang. When read-timeout is not nil
, and there is no input from the socket for more than read-timeout seconds, any reading function returns end-of-file
. The read-timeout does not limit the time inside read
, but the time between successful extractions of data from the socket. Therefore, if the reading needs several rounds it may take longer than read-timeout.
Using (setf stream:stream-read-timeout)
on the stream while it is inside a read function has undefined effects. However, the setf function can be used between calls to read functions. The read-timeout property of a stream can be read by (stream:stream-read-timeout stream)
The :write-timeout
initarg specifies the write timeout in seconds, or is nil
, meaning that there are no timeouts during writes (this is the default).
The write-timeout property is similar to read-timeout, but for write operations. If flushing the stream buffer takes too long then error
is called.
The initargs :ssl-ctx
, :ssl-side
, :ctx-configure-callback
, :ssl-configure-callback
and :handshake-timeout
can be be supplied to create and configure socket streams with SSL processing. See Keyword arguments for use with SSL for more details.
If :tlsext-host-name
initarg is a string then the SNI extension in the SSL connection to set to its value.
If there is a non-local exit while initializing the socket-stream
(the most common reason being a SSL handshake failure when using SSL), then the stream will be closed. This will cause the socket to be closed as well.
cl:read
, cl:read-char
and so on) can also wait properly. You can also use process-wait and similar functions with cl:listen
in the wait-function, but you will need to use with-noticed-socket-stream.socket-stream
is normally a socket object in the operating system sense. On Unix and Microsoft Windows it is an integer corresponding to a socket as returned from the C functions socket and accept. It can also be a Java socket object, see Socket streams with Java sockets and SSL on Android for details.(setf socket-steam-socket)
can be used to set the socket object in the stream, and can also set it to nil
. When there is already a socket in the stream, (setf socket-steam-socket)
closes it before setting the slot to the new socket. The function replace-socket-stream-socket can be used to set the socket without closing the old one.The following makes a bidirectional stream connected to a socket specified by handle.
(make-instance 'comm:socket-stream
:socket handle
:direction :io
:element-type 'base-char)
This example creates a socket stream with a read-timeout:
(make-instance 'comm:socket-stream
:handle handle
:direction :input
:read-timeout 42)
The following form illustrates character I/O in a binary socket-stream
:
(with-open-stream (x
(comm:open-tcp-stream
"localhost" 80
:element-type '(unsigned-byte 8)))
(write-sequence (format nil "GET / HTTP/1.0~%~%") x)
(force-output x)
(let ((res (make-array 20 :element-type 'base-char)))
(values (read-sequence res x) res)))
The following form illustrates binary I/O in a base-char
socket-stream
:
(with-open-stream (x
(comm:open-tcp-stream
"localhost" 80
:element-type 'base-char))
(write-sequence
(map '(simple-array (unsigned-byte 8) 1)
'char-code
(format nil "GET / HTTP/1.0~%~%"))
x)
(force-output x)
(let ((res (make-array 20
:element-type
'(unsigned-byte 8))))
(values (read-sequence res x)
(map 'string 'code-char res))))
connect-to-tcp-server
open-tcp-stream
start-up-server
stream-read-timeout
wait-for-input-streams
replace-socket-stream-socket
TCP and UDP socket communication and SSL
LispWorks User Guide and Reference Manual - 20 Sep 2017