usocket - Universal Socket Library
Version: 0.8.3
Licence: MIT
Repository: usocket/usocket
See also: awesome-cl#websockets
This page was possible due to the excellent official documentation.
In case of any inaccuracies, ambiguities or suggestions, please create an issue here.
GETTING STARTED
For the examples below, we assume the user has access to netcat
. A pure lisp example can be found here.
0] Firstly, we
CL-USER> (add-package-local-nickname :u :usocket)
#<PACKAGE "COMMON-LISP-USER">
Example 1 - TCP and Netcat
1] On a terminal, we start a TCP server using netcat
$ nc -lv localhost 8001
Listening on [localhost] (family 0, port 8001)
On the lisp side, we connect to the server
CL-USER> (defparameter socket (u:socket-connect "localhost" 8001))
SOCKET
$ nc -lv localhost 8001
Listening on [localhost] (family 0, port 8001)
Connection from localhost 56888 received!
2] Once the connection is established, we send some data from lisp to the netcat server:
CL-USER> (defparameter str (u:socket-stream socket))
STR
CL-USER> (defun write-and-flush (string)
(write-string string str)
(force-output str))
WRITE-AND-FLUSH
CL-USER> (write-and-flush "hello")
NIL
That should cause hello
appear on netcat.
3] We also do the reverse: type world
on the terminal and press Ctrl+D
to flush it.
On the lisp side,
CL-USER> (loop :while (listen str) :do (write-char (read-char str)))
world
NIL
Example 2 - Netcat and UDP
The process is similar in this case; however, instead of reading and writing to the
stream, one uses socket-send and socket-receive. The first step is the same, except we start netcat as nc -luv
.
2] Once the connection is established, we send some data from lisp to the netcat server:
CL-USER> (u:socket-send socket "hello" nil)
NIL
That should cause hello
appear on netcat.
3] We also do the reverse: type world
on the terminal and press Ctrl+D
to flush it.
On the lisp side,
CL-USER> (u:socket-receive socket (make-string 10) nil)
"world\0\0\0"
5
#(127 0 0 1)
8001
The final state of the terminal should be
$ nc -luv localhost 8001
Listening on [localhost] (family 0, port 8001)
Connection from localhost 60367 received!
helloworld
More examples and FAQs
See the Cookbook and the FAQs in official documentation.
Conventions
Specification of a host
or local-host
parameter
A host
or local-host
parameter may be any one of
- 32-bit positive integer,
- A four element integer list representing IPv4 address, i.e.
#(127 0 0 1)
- a string containing an IP addres in dotted notation, or
- a host name to be resolved through DNS lookup.
Sockets and Servers
The system consists of two subsystems usocket
and usocket-server
. Loading usocket
avoids loading the server related functions and helps keeps the core small.
To load the whole thing, one needs to :depends-on
both "usocket"
and "usocket-server"
in the ASDF file. Both these work with the :usocket
package.
Sockets
Types of Sockets
Socket Functions
Accessors
Select
Servers
The following are available in the usocket
package after loading both usocket
and usocket-server
systems.
API DOCUMENTATION
usocket
maintainers are committed to the interface described below for
the entire 0.x phase of the library. When 1.0 comes some of the
functionality may be split up in different functions and guarantees may
change because of it.
*auto-port*
Variable
Default Value: 0
The port number to use with socket-listen to make the socket listen on a random available port. The port number assigned can be retrieved from the returned socket by calling get-local-port.
*backend*
Variable
Default Value: :NATIVE
*default-event-base*
No documentation found for *default-event-base*
*remote-host*
Special variable used in socket-server's handler function for getting current client address. (Start from USOCKET 0.5)
*remote-port*
Special variable used in socket-server's handler function for getting current client port. (Start from USOCKET 0.5)
*version*
Variable
Default Value: "0.8.3"
usocket version string
*wildcard-host*
Variable
Default Value: #(0 0 0 0)
Hostname to pass when all interfaces in the current system are to be bound. If this variable is passed to socket-listen, IPv6 capable systems will also listen for IPv6 connections.
+max-datagram-packet-size+
Constant: 65507
The theoretical maximum amount of data in a UDP datagram.
The IPv4 UDP packets have a 16-bit length constraint, and IP+UDP header has 28-byte.
IP_MAXPACKET = 65535, /* netinet/ip.h */
sizeof(struct ip) = 20, /* netinet/ip.h */
sizeof(struct udphdr) = 8, /* netinet/udp.h */
65535 - 20 - 8 = 65507
(But for UDP broadcast, the maximum message size is limited by the MTU size of the underlying link)
add-waiter
Function: (add-waiter wait-list input)
address-in-use-error
Condition
address-not-available-error
Condition
bad-file-descriptor-error
Condition
connection-aborted-error
Condition
connection-refused-error
Condition
connection-reset-error
Condition
datagram-usocket
Class
UDP (inet-datagram) socket
- Direct superclasses: usocket
Direct Slots
connected-p
Initargs: :CONNECTED-P
Reader: CONNECTED-P
Writer: (SETF CONNECTED-P)
Used to identify if the datagram is connected. It will be setup by socket-connect, and used by socket-send and socket-receive.
datagram-usocket-p
Function: (datagram-usocket-p socket)
deadline-timeout-error
Condition
default-tcp-handler
Function: (default-tcp-handler stream)
default-udp-handler
Function: (default-udp-handler buffer)
dotted-quad-to-vector-quad
Function: (dotted-quad-to-vector-quad string)
echo-tcp-handler
Function: (echo-tcp-handler stream)
get-host-by-name
Function: (get-host-by-name name)
0.7.1+: if there're IPv4 addresses, return the first IPv4 address.
get-hosts-by-name
Function: (get-hosts-by-name name)
get-local-address
Generic Function: (get-local-address socket)
Returns the IP address of the socket.
get-local-name
Generic Function: (get-local-name socket)
Returns the IP address and port of the socket as values.
This function applies to both stream-usocket and server-stream-usocket type objects.
get-local-port
Generic Function: (get-local-port socket)
Returns the IP port of the socket.
This function applies to both stream-usocket and server-stream-usocket type objects.
get-peer-address
Generic Function: (get-peer-address socket)
Returns the IP address of the peer the socket
is connected to.
get-peer-name
Generic Function: (get-peer-name socket)
Returns the IP address and port of the peer
the socket
is connected to as values.
get-peer-port
Generic Function: (get-peer-port socket)
Returns the IP port of the peer the socket
to.
get-random-host-by-name
Function: (get-random-host-by-name name)
0.7.1+: if there're IPv4 addresses, only return a random IPv4 address.
hbo-to-dotted-quad
Function: (hbo-to-dotted-quad integer)
Host-byte-order integer to dotted-quad string conversion utility.
hbo-to-vector-quad
Function: (hbo-to-vector-quad integer)
Host-byte-order integer to dotted-quad string conversion utility.
host-byte-order
Generic Function: (host-byte-order address)
host-down-error
Condition
host-or-ip
Generic Function: (host-or-ip condition)
host-to-hostname
Function: (host-to-hostname host)
Translate a string, vector quad or 16 byte IPv6 address to a stringified hostname.
host-unreachable-error
Condition
insufficient-implementation
Condition
The ancestor of all errors usocket may generate
because of insufficient support from the underlying implementation
with respect to the arguments given to function
.
One call may signal several errors, if the caller allows processing to continue.
integer-to-octet-buffer
Function: (integer-to-octet-buffer integer buffer octets &key (start 0))
interrupted-condition
Condition
invalid-argument-error
Condition
invalid-socket-error
Condition
invalid-socket-stream-error
Condition
ip-from-octet-buffer
Macro: (ip-from-octet-buffer buffer &key (start 0))
ip-to-octet-buffer
Macro: (ip-to-octet-buffer ip buffer &key (start 0))
ip/=
Function: (ip/= ip1 ip2)
ip=
Function: (ip= ip1 ip2)
ipv6-host-to-vector
Function: (ipv6-host-to-vector string)
make-wait-list
Function: (make-wait-list waiters)
network-down-error
Condition
network-reset-error
Condition
network-unreachable-error
Condition
no-buffers-error
Condition
ns-condition
Condition
Parent condition for all name resolution conditions.
Direct Slots
host-or-ip
Initargs: :HOST-OR-IP
Readers: HOST-OR-IP
Writers: (SETF HOST-OR-IP)
ns-error
Condition
Parent error for all name resolution errors.
ns-host-not-found-error
Condition
ns-no-recovery-error
Condition
ns-try-again-condition
Condition
ns-unknown-condition
Condition
Condition raised when there's no other - more applicable - condition available.
ns-unknown-error
Condition
Error raised when there's no other - more applicable - error available.
octet-buffer-to-integer
Function: (octet-buffer-to-integer buffer octets &key (start 0))
operation-not-permitted-error
Condition
operation-not-supported-error
Condition
port-from-octet-buffer
Macro: (port-from-octet-buffer buffer &key (start 0))
port-to-octet-buffer
Macro: (port-to-octet-buffer port buffer &key (start 0))
protocol-not-supported-error
Condition
remove-all-waiters
Function: (remove-all-waiters wait-list)
remove-waiter
Function: (remove-waiter wait-list input)
shutdown-error
Condition
socket
Generic Function: (socket object)
socket-accept
Generic Function: (socket-accept socket &key element-type)
Accepts a connection from socket
, returning a stream-socket.
The stream associated with the socket returned has element-type
when
explicitly specified, or the element-type
of the socket
(as used when it was created by the call to socket-listen) otherwise.
socket-close
Generic Function: (socket-close usocket)
Close a previously opened usocket after flushing it.
socket-condition
Condition
Parent condition for all socket related conditions.
Direct Slots
socket
Initargs: :SOCKET
Readers: :USOCKET-SOCKET
Writers: (SETF :USOCKET-SOCKET)
socket-connect
Function: (socket-connect host port &key (protocol :stream)
(element-type (quote character)) timeout deadline
(nodelay t nodelay-specified) local-host local-port &aux
(sockopt-tcp-nodelay-p (fboundp (quote sockopt-tcp-nodelay))))
Returns a stream-usocket (TCP) object if protocol
is :stream
and
datagram-socket (UDP) if it is :datagram
.
Connects the socket to host
on port
. host
is assumed to be a string or
an IP address represented in vector notation, such as #(192 168 1 1)
.
port
is assumed to be an integer.
element-type
specifies the element type to use when constructing the
stream associated with the stream-socket. The default is 'character
,
but (unsigned-byte 8)
is also a valid value.
timeout
is a integer, it represents the socket option
SO_RCVTIMEO
(read timeout), in seconds.
deadline
is only supported in Clozure CL and Digitool MCL
local-host
andlocal-port
, when specified, will cause the socket calling bind() on local address. This is useful for selecting interfaces to send, or listening on UDP port. Note: use only one of them are allowed when reasonable (listen on wildcard address, or bind to random free port).
nodelay
allows to disable/enable Nagle's algorithm.
If this parameter is omitted, the behaviour is inherited from the
CL implementation (in most cases, Nagle's algorithm is
enabled by default, but for example in ACL it is disabled).
If the parameter is specified, one of these three values is possible:
T
- Disable Nagle's algorithm; signals an unsupported condition if the implementation does not support explicit manipulation with that option.NIL
- Leave Nagle's algorithm enabled on the socket; signals an unsupported condition if the implementation does not support explicit manipulation with that option.:IF-SUPPORTED
- Disables Nagle's algorithm if the implementation allows this, otherwises just ignore this option.
socket-error
Condition
Parent error for all socket related errors
socket-listen
Function: (socket-listen host port &key reuseaddress
(reuse-address NIL reuse-address-supplied-p) (backlog 5)
(element-type (quote character)))
Bind to interface host
on port
. host
should be the
representation of an ready-interface address. The implementation is
not required to do an address lookup, making no guarantees that
hostnames will be correctly resolved. If *wildcard-host* or NIL
is
passed for host, the socket will be bound to all available
interfaces for the system. port can be selected by the IP stack by
passing *auto-port*. A port
value of 0 indicates a request for
a random free port.
Returns an object of type stream-server-usocket.
reuse-address
and backlog
are advisory parameters for setting socket
options at creation time. element-type
is the element type of the
streams to be created by socket-accept. reuseaddress
is supported for
backward compatibility (but deprecated); when both reuseaddress
and
reuse-address
have been specified, the latter takes precedence.
socket-option
Generic Function: (socket-option socket option &key)
Get a socket's internal options
socket-receive
Generic Function: (socket-receive usocket buffer length &key element-type)
Receive packets from a previously opened usocket.
Returns 4 values: (values buffer size host port)
Receive data from a datagram socket, and return 4 values:
return-buffer
, return-length
, remote-host
, and remove-port
.
If the datagram socket was created by socket-connect
with a timeout
keyword argument, this function will block at most
that timeout value (in seconds). (Start from USOCKET 0.5)
socket should be a datagram-usocket
buffer
is a Lisp vector of type (simple-array (unsigned-byte 8) *)
. Using nil
here
is also allowed, new buffer will be created to hold data.
length
is used to specify the length of a exist buffer for
receiving at most these data. Using nil
here is allowed, and the
actual length of buffer
will be used; when buffer
is also nil
,
a default maximum length (65507) will be used.
socket-send
Generic Function: (socket-send usocket buffer length &key host port offset)
Send packets through a previously opened usocket.
buffer
is a Lisp vector, type of
(simple-array (unsigned-byte 8) *)
.
length
is used to tell socket-send the actual useful length of data buffer for sending to socket.
host
and port
are used for unconnected datagram sockets, for
sending to specific destination.
The return value indicates the number of bytes sent. (Start from USOCKET 0.5)
socket-server
Function: (socket-server host port function &optional arguments &key
in-new-thread (protocol :stream) (timeout 1)
(max-buffer-size +max-datagram-packet-size+) element-type
(reuse-address t) multi-threading name)
Create a simple TCP or UDP socket server. (Start from USOCKET 0.5)
host
names a local interface,-
port
names a local port, -
function
names a function object, which is used to handle TCP or UDP connections. This is explained below. -
arguments
is a list used for passing extra arguments to user-definedfunction
. -
in-new-thread
is a boolean, default isnil
. When it'sT
, the server will be created in a new thread and socket-server returns immediately in current thread. -
protocol
could be either:stream
(default) or:datagram
, which decide the socket server is TCP server or UDP server. -
timeout
is UDP only, it provides the internal socket-receive call (in UDP event loop of the socket server) a read timeout, default value is 1 (second). -
max-buffer-size
is UDP only, it's the max UDP data buffer size when handling UDP packets, default value is 65507. element-type
is TCP only, it's element-type of the stream provided for user-defined function,reuse-address
is TCP only, it's a boolean option for internal call of socket-listen in the socket server,multi-threading
is TCP only, it's a boolean, default value isnil
. When it'sT
, each client connection will cause a new thread being created to handle that client, so that the TCP server could handle multiple clients at the same time. (Note: since UDP server is connectionless, it can always handle multiple clients, as long as the handler function run fast enough)
TCP HANDLER FUNCTION
Following forms a valid template function for TCP:
(defun default-tcp-handler (stream) ; null
(declare (type stream stream))
(terpri stream))
Note:
-
You don't need to close the stream as
socket-server
will do that for you. -
More function arguments can be defined, and these extra arguments must be feeded as the optional
arguments
ofsocket-server
UDP HANDLER FUNCTION
The handler function for UDP is buffer-based, that is, you receive a buffer of data as input, and you return another buffer for output. A template function is a simple UDP echo server:
(defun default-udp-handler (buffer) ; echo
(declare (type (simple-array (unsigned-byte 8) *) buffer))
buffer)
Note:
-
data length is the length of the whole buffer.
-
Sometimes you may want to know the client's IP address and sending port, these informations are specially bounded on variables *remote-host* and *remote-port* when handler function is running.
socket-shutdown
Generic Function: (socket-shutdown usocket direction)
The socket-shutdown
call causes all or part of a full-duplex
connection on the socket associated with sockfd to be shut down.
- If
direction
is:input
, further receptions will be disallowed. - If
direction
is:output
, further transmissions will be disallowed. - If
direction
is:io
, further receptions and transmissions will be disallowed. (Starting from USOCKET 0.6.4)
socket
should be a datagram-usocket.
socket-state
Generic Function: (socket-state socket)
NIL - not ready
:READ - ready to read
:READ-WRITE - ready to read and write
:WRITE - ready to write
socket-stream
Generic Function: (socket-stream object)
socket-type-not-supported-error
Condition
socket-warning
No documentation found for socket-warning
stream-server-usocket
Class
Socket which listens for stream connections to be initiated from remote sockets.
- Direct superclasses: usocket
Direct Slots
element-type
Initargs: :ELEMENT-TYPE
Initform: 'CHARACTER
Reader: ELEMENT-TYPE
Indicates the default element-type to be used when constructing streams off this socket when no element type is specified in the call to socket-accept.
stream-server-usocket-p
Function: (stream-server-usocket-p socket)
stream-usocket
Class
Stream socket class. Contrary to other sockets, these sockets may be closed either
with the socket-close
method or by closing the associated stream
(which can be retrieved with the socket-stream
accessor).
- Direct superclasses: usocket
Direct Slots
stream
Initargs: :STREAM
Readers: SOCKET-STREAM
Writers: (SETF SOCKET-STREAM)
Used to store the stream associated with the tcp socket connection. When you want to write to the socket stream, use this function.
stream-usocket-p
Function: (stream-usocket-p socket)
timeout-error
Condition
unimplemented
Macro: (unimplemented feature context)
Condition
Signalled if a certain feature might be implemented, based on the features of the underlying implementation, but hasn't been implemented yet.
unknown-condition
Condition
Condition raised when there's no other - more applicable - condition available.
unknown-error
Condition
Error raised when there's no other - more applicable - error available.
unsupported
Macro: (unsupported feature context &key minimum)
Condition
Signalled when the underlying implementation doesn't allow supporting the requested feature.
When you see this error, go bug your vendor/implementation developer!
usocket
Class
The main socket class.
Sockets should be closed using the socket-close method.
Direct Slots
socket
Initargs: :SOCKET
Readers: SOCKET
Writers: (SETF SOCKET)
Used to store sockets as used by the current implementation - may be any of socket handles, socket objects and stream objects
state
Initargs: :STATE
Readers: STATE
Writers: (SETF STATE)
Used to store socket state: NIL
(not ready), or :READ
(ready to read).
usocket-p
Function: (usocket-p socket)
vector-quad-to-dotted-quad
Function: (vector-quad-to-dotted-quad vector)
vector-to-ipv6-host
Function: (vector-to-ipv6-host vector)
wait-for-input
Function: (wait-for-input socket-or-sockets &key timeout ready-only &aux
(single-socket-p (usocket-p socket-or-sockets)))
Waits for one or more sockets to become ready for reading from the socket. This is like the UNIX's "select" function.
When timeout
(a non-negative real number) is
specified, wait timeout
seconds, or wait indefinitely when
it isn't specified. A timeout value of 0 (zero) means polling.
Returns two values:
- the first value is the list of sockets which
are readable (or in case of server sockets acceptable).
NIL
may be returned for this value either when waiting timed out or when it was interrupted (EINTR). - The second value is a real number
indicating the time remaining within the timeout period or
NIL
if none.
Without the ready-only
arg, wait-for-input
will return all sockets in
the original list you passed it. This prevents a new list from being
consed up. Some users of USOCKET were reluctant to use it if it
wouldn't behave that way, expecting it to cost significant performance
to do the associated garbage collection.
Without the ready-only
arg, you need to check the socket state
slot for
the values documented in usocket.lisp in the usocket class.
with-client-socket
Macro: (with-client-socket (socket-var stream-var &rest socket-connect-args)
&body body)
Bind the socket resulting from a call to socket-connect with the arguments socket-connect-args to socket-var and if stream-var is non-nil, bind the associated socket stream to it.
with-connected-socket
Macro: (with-connected-socket (var socket) &body body)
Bind socket to var, ensuring socket destruction on exit.
body is only evaluated when var is bound to a non-null value.
The body is an implied progn form.
with-mapped-conditions
Macro: (with-mapped-conditions (&optional socket host-or-ip) &body body)
with-server-socket
Macro: (with-server-socket (var server-socket) &body body)
Bind server-socket to var, ensuring socket destruction on exit.
body is only evaluated when var is bound to a non-null value.
The body is an implied progn form.
with-socket-listener
Macro: (with-socket-listener (socket-var &rest socket-listen-args) &body body)
Bind the socket resulting from a call to socket-listen with arguments socket-listen-args to socket-var.