Networking - Socket Addresses

Changed in version 1.3.0: Added the ability to create addresses directly through the constructor.

Under the BSD socket model, sockets are bound or connected to a specific single address, which is of a single address family, protocol and socket type. In the real world, this is not sufficient; with dual stack networks being common but not too common, you want to be able to connect to IPv6 if possible then fall back to IPv4.

Tinlok builds socket abstractions around this model by separating out an address a socket will bind to with the actual networking address using two classes: SocketAddress and ConnectionInfo.

ConnectionInfo

A ConnectionInfo instance contains the raw information a socket can use to open and connect or bind to. It contains the socket constants for a BSD socket, and is subclassed for things such as internet sockets or unix sockets.

For internet sockets, the InetConnectionInfo abstract class exists. It wraps an IPAddress and an integer port.

Usually, a ConnectionInfo subclass instance can be created by passing the IP and port:

val ip = IPv6Address.of("::1")
val info = TcpConnectionInfo(ip, 80)
// info can now be used to bind a server socket

The wildcard address and the localhost address can be created using helper methods:

val wildcard = TcpConnectionInfo.wildcard(22)
val localhost = TcpConnectionInfo.localhost(21)

A ConnectionInfo exposes the family, type, and protocol. See Networking - Enums.

SocketAddress

A SocketAddress is a Set of multiple ConnectionInfo instances as returned by the underlying system DNS resolver, representing a single remote endpoint. It is passed to a socket to connect to the remote server over all available address families.

A SocketAddress is usually created from a helper method on the companion object, rather than being passed directly:

val tcp = TcpSocketAddress.resolve("toaru-project.com")
val udp = UdpSocketAddress.resolve("some-udp-service-i-couldnt-think-of-any.arpa").

Note

In library design, anywhere you want to do DNS resolution you should allow a user to pass a resolver parameter to customise the DNS resolver used.

These addresses can then be passed to a client socket to connect with.