Some very new code, not completely tested.
The
<client>
and
<server>
words used to take a host/port pair, and a port number, respectively. This was too limiting. Now both words take address specifiers, of which are there four types:
"/path/to/socket" <local>
- an IPC socket with the given path (Unix domain sockets on Unix)"dotted.quad" 123 <inet4>
- an IPv4 address"ipv6.addr" 1234 <inet6>
- an IPv6 address"hostname" "http" <inet>
- Internet host named by DNS entry; will be either IPv4 or IPv6
Note that in most cases,
<client>
will be called with an instance of
inet
; this invokes the domain name resolver, which may produce a list of multiple IPv4 and IPv6 addresses. Factor tries each one in turn until a connection succeeds. This is the expected behavior for client sockets, since users generally input host names and not IP addresses, and don't care if the connection is made over IPv4 or IPv6.
The
<server>
word requires an instance of the more specific
inet4
and
inet6
classes. Since in most cases, a server interested in connections on, say, port 8080 wants to receive connections over both IPv4 and IPv6, the
with-server
combinator should be used instead of calling
<server>
directly. Here's a usage example which waits for connections on port 8080 and sends "Hello, client" to each one:
8080 internet-server [ "Hello, client." print ] with-server
If your system is configured for IPv6, this example will spawn two threads, for IPv4 and IPv6 connections.
Server sockets can now be restricted to the loopback network interface by passing
8080 local-server
instead of
8080 internet-server
. Before this was provided by the Unix-only
loopback-server
module; this module is now obsolete.
The domain name resolver can now be invoked directly with the
resolve-host
word. Given a host name and port name or number, it returns a list of address specifiers.
UDP/IP works as before; words which used to take host/port pairs now take address specifiers. Note that the
inet
address specifier is not supported for UDP/IP; clients must first resolve the destination host name, and pick the appropriate address specifier, whether it be an IPv4 or IPv6 address, from the result.
Unix domain sockets are accessed with the
local
address specifier.
Stream Unix domain sockets are very commonly used, but a little-known fact is that datagram Unix domain sockets are supported too. Here is some proof.
Enter this in one listener:
"/tmp/dgram-dst" <local> <datagram>
dup receive
stream-close
Then this in another:
"/tmp/dgram-src" <local> <datagram>
B{ 1 2 3 4 5 } "/tmp/dgram-dst" <local> pick send
stream-close
The first machine should now have the following two objects on the stack:
B{ 1 2 3 4 }
T{ local f "/tmp/dgram-src" }
I still have to fix assorted bugs in this code. Also Windows network support is lagging; not only does it have to be updated to support address specifiers, but it is also missing UDP hooks at this stage.
I won't be adding more features to networking for a little while, but the next thing I will do is probably raw sockets.