#
Chapter 4
Networking

The Scheme Shell provides a BSD-style sockets interface. There is not an official standard for a network interface for scsh to adopt (this is the subject of the forthcoming Posix.8 standard). However, Berkeley sockets are a de facto standard, being found on most Unix workstations and PC operating systems.

It is fairly straightforward to add higher-level network protocols such as smtp, telnet, or http on top of the the basic socket-level support scsh provides. The Scheme Underground has also released a network library with many of these protocols as a companion to the current release of scsh. See this code for examples showing the use of the sockets interface.

## 4.1 High-level interface

For convenience, and to avoid some of the messy details of the socket interface, we provide a high level socket interface. These routines attempt to make it easy to write simple clients and servers without having to think of many of the details of initiating socket connections. We welcome suggested improvements to this interface, including better names, which right now are solely descriptions of the procedure's action. This might be fine for people who already understand sockets, but does not help the new networking programmer.

`(socket-connect protocol-family socket-type . args)` ---> socket (procedure)

> `socket-connect` is intended for creating client applications. protocol-family is specified as either the `protocol-family/internet` or `protocol-family/unix`. socket-type is specified as either `socket-type/stream` or `socket-type/datagram`. See `socket` for a more complete description of these terms.

> The variable args list is meant to specify protocol family specific information. For Internet sockets, this consists of two arguments: a host name and a port number. For Unix sockets, this consists of a pathname.

> `socket-connect` returns a `socket` which can be used for input and output from a remote server. See `socket` for a description of the socket record.

`(bind-listen-accept-loop protocol-family proc arg)` ---> does-not-return (procedure)

> `bind-listen-accept-loop` is intended for creating server applications. protocol-family is specified as either the `protocol-family/internet` or `protocol-family/unix`. proc is a procedure of two arguments: a `socket` and a socket-address. arg specifies a port number for Internet sockets or a pathname for Unix sockets. See `socket` for a more complete description of these terms.

> proc is called with a socket and a socket address each time there is a connection from a client application. The socket allows communications with the client. The socket address specifies the address of the remote client.

> This procedure does not return, but loops indefinitely accepting connections from client programs.

## 4.2 Sockets

`(create-socket protocol-family type [protocol])` ---> socket (procedure)
`(create-socket-pair type)` ---> [socket1 socket2] (procedure)
`(close-socket socket)` ---> undefined (procedure)

> A socket is one end of a network connection. Three specific properties of sockets are specified at creation time: the protocol-family, type, and protocol.

> The protocol-family specifies the protocol family to be used with the socket. This also determines the address family of socket addresses, which are described in more detail below. Scsh currently supports the Unix internal protocols and the Internet protocols using the following constants:

> > `protocol-family/unspecified
> > protocol-family/unix
> > protocol-family/internet`

> The type specifies the style of communication. Examples that your operating system probably provides are stream and datagram sockets. Others maybe available depending on your system. Typical values are:

> > `socket-type/stream
> > socket-type/datagram
> > socket-type/raw`

> The protocol specifies a particular protocol to use within a protocol family and type. Usually only one choice exists, but it's probably safest to set this explicitly. See the protocol database routines for information on looking up protocol constants.

> New sockets are typically created with `create-socket`. However, `create-socket-pair` can also be used to create a pair of connected sockets in the `protocol-family/unix` protocol-family. The value of a returned socket is a socket record, defined to have the following structure:

> > `(define-record socket
> > family ; protocol family
> > inport ; input-port
> > outport) ; output-port`

> The `family` specifies the protocol family of the socket. The `inport` and `outport` fields are ports that can be used for input and output, respectively. For a stream socket, they are only usable after a connection has been established via `connect-socket` or `accept-connection`. For a datagram socket, outport can be immediately using `send-message`, and inport can be used after `bind` has created a local address.

> `close-socket` provides a convenient way to close a socket's port. It is preferred to explicitly closing the inport and outport because using `close` on sockets is not currently portable across operating systems.

`(port->socket port protocol-family)` ---> socket (procedure)

> This procedure turns port into a socket object. The port's underlying file descriptor must be a socket with protocol family protocol-family. `port->socket` comes in handy for writing servers which run as children of `inetd`: after receiving a connection `inetd` creates a socket and passes it as standard input to its child.

## 4.3 Socket addresses

The format of a socket-address depends on the address family of the socket. Address-family-specific routines are provided to convert protocol-specific addresses to socket addresses. The value returned by these routines is a socket-address record, defined to have the following visible structure:

> `(define-record socket-address
> family) ; address family`

The `family` is one of the following constants:

> `address-family/unspecified
> address-family/unix
> address-family/internet`

`(unix-address->socket-address pathname)` ---> socket-address (procedure)

> `unix-address->socket-address` returns a socket-address based on the string pathname. There is a system dependent limit on the length of pathname.

`(internet-address->socket-address host-address service-port)` ---> socket-address (procedure)

> `internet-address->socket-address` returns a socket-address based on an integer host-address and an integer service-port. Besides being a 32-bit host address, an Internet host address can also be one of the following constants:

> > `internet-address/any
> > internet-address/loopback
> > internet-address/broadcast`

> The use of `internet-address/any` is described below in `bind-socket`. `internet-address/loopback` is an address that always specifies the local machine. `internet-address/broadcast` is used for network broadcast communications.

> For information on obtaining a host's address, see the `host-info` function.

`(socket-address->unix-address socket-address)` ---> pathname (procedure)
`(socket-address->internet-address socket-address)` ---> [host-address service-port] (procedure)

> The routines `socket-address->internet-address` and `socket-address->unix-address` return the address-family-specific addresses. Be aware that most implementations don't correctly return anything more than an empty string for addresses in the Unix address-family.

## 4.4 Socket primitives

The procedures in this section are presented in the order in which a typical program will use them. Consult a text on network systems programming for more information on sockets.12 The last two tutorials are freely available as part of BSD. In the absence of these, your Unix manual pages for socket might be a good starting point for information.

`(connect-socket socket socket-address)` ---> undefined (procedure)

> `connect-socket` sets up a connection from a socket to a remote socket-address. A connection has different meanings depending on the socket type. A stream socket must be connected before use. A datagram socket can be connected multiple times, but need not be connected at all if the remote address is specified with each `send-message`, described below. Also, datagram sockets may be disassociated from a remote address by connecting to a null remote address.

`(bind-socket socket socket-address)` ---> undefined (procedure)

> `bind-socket` assigns a certain local socket-address to a socket. Binding a socket reserves the local address. To receive connections after binding the socket, use `listen-socket` for stream sockets and `receive-message` for datagram sockets.

> Binding an Internet socket with a host address of `internet-address/any` indicates that the caller does not care to specify from which local network interface connections are received. Binding an Internet socket with a service port number of zero indicates that the caller has no preference as to the port number assigned.

> Binding a socket in the Unix address family creates a socket special file in the file system that must be deleted before the address can be reused. See `delete-file`.

`(listen-socket socket backlog)` ---> undefined (procedure)

> `listen-socket` allows a stream socket to start receiving connections, allowing a queue of up to backlog connection requests. Queued connections may be accepted by `accept-connection`.

`(accept-connection socket)` ---> [new-socket socket-address] (procedure)

> `accept-connection` receives a connection on a socket, returning a new socket that can be used for this connection and the remote socket address associated with the connection.

`(socket-local-address socket)` ---> socket-address (procedure)
`(socket-remote-address socket)` ---> socket-address (procedure)

> Sockets can be associated with a local address or a remote address or both. `socket-local-address` returns the local socket-address record associated with socket. `socket-remote-address` returns the remote socket-address record associated with socket.

`(shutdown-socket socket how-to)` ---> undefined (procedure)

> `shutdown-socket` shuts down part of a full-duplex socket. The method of shutting done is specified by the how-to argument, one of:

> > `shutdown/receives
> > shutdown/sends
> > shutdown/sends+receives`

## 4.5 Performing input and output on sockets

`(receive-message socket length [flags])` ---> [string-or-`#f`socket-address] (procedure)
`(receive-message! socket string [start] [end] [flags])` ---> [count-or-`#f`socket-address] (procedure)
`(receive-message/partial socket length [flags])` ---> [string-or-`#f`socket-address] (procedure)
`(receive-message!/partial socket string [start] [end] [flags])` ---> [count-or-`#f`socket-address] (procedure)

`(send-message socket string [start] [end] [flags] [socket-address])` ---> undefined (procedure)
`(send-message/partial socket string [start] [end] [flags] [socket-address])` ---> count (procedure)

> For most uses, standard input and output routines such as `read-string` and `write-string` should suffice. However, in some cases an extended interface is required. The `receive-message` and `send-message` calls parallel the `read-string` and `write-string` calls with a similar naming scheme.

> One additional feature of these routines is that `receive-message` returns the remote socket-address and send-message takes an optional remote `socket-address`. This allows a program to know the source of input from a datagram socket and to use a datagram socket for output without first connecting it.

> All of these procedures take an optional flags field. This argument is an integer bit-mask, composed by or'ing together the following constants:

> > `message/out-of-band
> > message/peek
> > message/dont-route`

> See `read-string` and `write-string` for a more detailed description of the arguments and return values.

## 4.6 Socket options

`(socket-option socket level option)` ---> value (procedure)
`(set-socket-option socket level option value)` ---> undefined (procedure)

> `socket-option` and `set-socket-option` allow the inspection and modification, respectively, of several options available on sockets. The level argument specifies what protocol level is to be examined or affected. A level of `level/socket` specifies the highest possible level that is available on all socket types. A specific protocol number can also be used as provided by `protocol-info`, described below.

> There are several different classes of socket options. The first class consists of boolean options which can be either true or false. Examples of this option type are:

> > `socket/debug
> > socket/accept-connect
> > socket/reuse-address
> > socket/keep-alive
> > socket/dont-route
> > socket/broadcast
> > socket/use-loop-back
> > socket/oob-inline
> > socket/use-privileged
> > socket/cant-signal
> > tcp/no-delay`

> Value options are another category of socket options. Options of this type are an integer value. Examples of this option type are:

> > `socket/send-buffer
> > socket/receive-buffer
> > socket/send-low-water
> > socket/receive-low-water
> > socket/error
> > socket/type
> > ip/time-to-live
> > tcp/max-segment`

> A third option type specifies how long for data to linger after a socket has been closed. There is only one option of this type: `socket/linger`. It is set with either `#f`to disable it or an integer number of seconds to linger and returns a value of the same type upon inspection.

> The fourth and final option type of this time is a timeout option. There are two examples of this option type: `socket/send-timeout` and `socket/receive-timeout`. These are set with a real number of microseconds resolution and returns a value of the same type upon inspection.

## 4.7 Database-information entries

`(host-info name-or-socket-address)` ---> host-info (procedure)
`(network-info name-or-socket-address)` ---> network-info or `#f` (procedure)
`(service-info name-or-number [protocol-name])` ---> service-info or `#f` (procedure)
`(protocol-info name-or-number)` ---> protocol-info or `#f` (procedure)

> `host-info` allows a program to look up a host entry based on either its string name or socket-address. The value returned by this routine is a host-info record, defined to have the following structure:

> > `(define-record host-info
> > name ; Host name
> > aliases ; Alternative names
> > addresses) ; Host addresses`

> `host-info` could fail and raise an error for one of the following reasons:

> > `herror/host-not-found
> > herror/try-again
> > herror/no-recovery
> > herror/no-data
> > herror/no-address`

> `network-info` allows a program to look up a network entry based on either its string name or socket-address. The value returned by this routine is a network-info record, defined to have the following structure:

> > `(define-record network-info
> > name ; Network name
> > aliases ; Alternative names
> > net) ; Network number`

> `service-info` allows a program to look up a service entry based on either its string name or integer port. The value returned by this routine is a service-info record, defined to have the following structure:

> > `(define-record service-info
> > name ; Service name
> > aliases ; Alternative names
> > port ; Port number
> > protocol) ; Protocol name`

> `protocol-info` allows a program to look up a protocol entry based on either its string name or integer number. The value returned by this routine is a protocol-info record, defined to have the following structure:

> > `(define-record protocol-info
> > name ; Protocol name
> > aliases ; Alternative names
> > number) ; Protocol number)`

> `network-info`, `service-info` and `protocol-info` return `#f`if the specified entity was not found.

12 Some recommended ones are:

- ``Unix Network Programming'' by W. Richard Stevens

- ``An Introductory 4.3BSD Interprocess Communication Tutorial.'' (reprinted in UNIX Programmer's Supplementary Documents Volume 1, PS1:7)

- ``An Advanced 4.3BSD Interprocess Communication Tutorial.'' (reprinted in UNIX Programmer's Supplementary Documents Volume 1, PS1:8)