All Manuals > LispWorks® User Guide and Reference Manual > 32 The COMM Package

socket-stream Class

Summary

The socket stream class.

Package

comm

Superclasses

buffered-stream

Initargs
:socket
A socket handle.
:direction
One of :input, :output, or :io.
:element-type
One of base-char, (signed-byte 8) and (unsigned-byte 8).
:read-timeout
A positive number or nil.
:write-timeout
A positive number or nil.
:ssl-ctx
A symbol, a foreign pointer or a ssl-abstract-context.
:ssl-side
One of the keywords :client, :server or :both. The default value is :server.
:ctx-configure-callback
A function designator or nil.
:ssl-configure-callback
A function designator or nil.
:handshake-timeout
A real or nil (the default).
:tlsext-host-name
A string or nil.
Accessors

socket-stream-socket
stream:stream-read-timeout
stream:stream-write-timeout

Description

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

Notes
  1. The function wait-for-input-streams and wait-for-input-streams-returning-first are a convenient interface for waiting for input from socket streams. The standard I/O functions (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.
  2. The socket object in a socket-stream is normally a socket object in the operating system sense. On Unix-like systems 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 25.9 Socket streams with Java sockets and SSL on Android for details.
  3. (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.
  4. Errors while doing I/O on a socket-stream are signaled using the condition class socket-io-error.
Examples

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))))
See also

connect-to-tcp-server
open-tcp-stream
start-up-server
wait-for-input-streams
replace-socket-stream-socket
socket-io-error
create-ssl-client-context
create-ssl-server-context
25 TCP and UDP socket communication and SSL
25 TCP and UDP socket communication and SSL


LispWorks® User Guide and Reference Manual - 01 Dec 2021 19:30:26