Java Unix Domain Socket implementation providing AF_UNIX, AF_TIPC, AF_VSOCK, and AF_SYSTEM socket support with traditional and NIO APIs
—
Comprehensive addressing system for Unix Domain Sockets and other socket families, supporting file paths, abstract namespace, and flexible address creation and management.
import java.io.*;
import java.net.*;
import java.nio.file.*;
import org.newsclub.net.unix.AFUNIXSocketAddress;
import org.newsclub.net.unix.AFSocketAddress;
import org.newsclub.net.unix.AFException;Primary addressing class for Unix Domain Socket connections, supporting both file system paths and abstract namespace addressing.
/**
* Unix Domain Socket addressing implementation
*/
public final class AFUNIXSocketAddress extends AFSocketAddress {
/**
* Creates an AFUNIXSocketAddress for the given file
* @param socketFile The socket file path
* @return AFUNIXSocketAddress instance
* @throws AFException if address creation fails
*/
public static AFUNIXSocketAddress of(File socketFile) throws AFException;
/**
* Creates an AFUNIXSocketAddress for the given path
* @param socketPath The socket path
* @return AFUNIXSocketAddress instance
* @throws AFException if address creation fails
*/
public static AFUNIXSocketAddress of(Path socketPath) throws AFException;
/**
* Creates an AFUNIXSocketAddress for the given path string
* @param pathname The socket path as string
* @return AFUNIXSocketAddress instance
* @throws AFException if address creation fails
*/
public static AFUNIXSocketAddress of(String pathname) throws AFException;
/**
* Creates an AFUNIXSocketAddress for a new temporary file
* @return AFUNIXSocketAddress instance for temporary socket
* @throws IOException if temporary file creation fails
*/
public static AFUNIXSocketAddress ofNewTempFile() throws IOException;
/**
* Creates an AFUNIXSocketAddress from a byte array
* @param bytes The address as byte array
* @return AFUNIXSocketAddress instance
* @throws AFException if address creation fails
*/
public static AFUNIXSocketAddress of(byte[] bytes) throws AFException;
/**
* Creates an AFUNIXSocketAddress from a URI
* @param uri The socket URI
* @return AFUNIXSocketAddress instance
* @throws AFException if address creation fails
*/
public static AFUNIXSocketAddress of(URI uri) throws AFException;
/**
* Creates an AFUNIXSocketAddress for the given file with port
* @param socketFile The socket file path
* @param port The port number
* @return AFUNIXSocketAddress instance
* @throws AFException if address creation fails
*/
public static AFUNIXSocketAddress of(File socketFile, int port) throws AFException;
/**
* Creates an AFUNIXSocketAddress in the abstract namespace (Linux only)
* @param name The abstract socket name
* @return AFUNIXSocketAddress instance for abstract socket
* @throws AFException if address creation fails
*/
public static AFUNIXSocketAddress inAbstractNamespace(String name) throws AFException;
// Address properties
public File getFile() throws FileNotFoundException;
public Path getPath() throws FileNotFoundException;
public String getPathname();
public boolean isInAbstractNamespace();
// Address validation
public boolean hasFilename();
public boolean exists();
// Address properties
public int getPort();
public byte[] toBytes();
public URI toURI() throws IOException;
// Compatibility methods
public String toString();
public boolean equals(Object obj);
public int hashCode();
}Usage Examples:
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.newsclub.net.unix.*;
// File-based socket addressing
File socketFile = new File("/tmp/my-app.sock");
AFUNIXSocketAddress addr1 = AFUNIXSocketAddress.of(socketFile);
// Path-based socket addressing
Path socketPath = Paths.get("/var/run/service.sock");
AFUNIXSocketAddress addr2 = AFUNIXSocketAddress.of(socketPath);
// String-based socket addressing
AFUNIXSocketAddress addr3 = AFUNIXSocketAddress.of("/tmp/string-socket.sock");
// Temporary socket file
AFUNIXSocketAddress tempAddr = AFUNIXSocketAddress.ofNewTempFile();
System.out.println("Temporary socket: " + tempAddr.getFile());
// Abstract namespace (Linux only)
AFUNIXSocketAddress abstractAddr = AFUNIXSocketAddress.inAbstractNamespace("my-abstract-socket");
System.out.println("Abstract socket: " + abstractAddr.getPathname());
System.out.println("Is abstract: " + abstractAddr.isInAbstractNamespace());
// Address validation
if (addr1.exists()) {
System.out.println("Socket file exists");
}
if (addr1.hasFilename()) {
System.out.println("Address has filename: " + addr1.getFile().getName());
}Common patterns for creating socket addresses in different scenarios:
// Server socket binding
public AFUNIXSocketAddress createServerAddress() throws IOException {
// Use temporary file for ephemeral server
return AFUNIXSocketAddress.ofNewTempFile();
}
// Client connection address
public AFUNIXSocketAddress createClientAddress(String serviceName) throws AFException {
// Connect to well-known service socket
File serviceSocket = new File("/var/run/" + serviceName + ".sock");
return AFUNIXSocketAddress.of(serviceSocket);
}
// Application-specific socket
public AFUNIXSocketAddress createAppSocket(String appName) throws AFException {
String userHome = System.getProperty("user.home");
File socketFile = new File(userHome + "/.config/" + appName + "/socket");
return AFUNIXSocketAddress.of(socketFile);
}
// Process-specific socket
public AFUNIXSocketAddress createProcessSocket() throws AFException {
long pid = ProcessHandle.current().pid();
String socketPath = "/tmp/app-" + pid + ".sock";
return AFUNIXSocketAddress.of(socketPath);
}Abstract base class for all AF socket address implementations.
/**
* Base class for all AF socket addresses
*/
public abstract class AFSocketAddress extends SocketAddress {
// Address comparison
public abstract boolean equals(Object obj);
public abstract int hashCode();
public abstract String toString();
// Address properties
public abstract byte[] getBytes();
public abstract int getAddressFamily();
// Utility methods
public abstract boolean hasFilename();
public abstract String getHostname();
}Address implementations for other socket families supported by junixsocket:
/**
* TIPC socket addressing for cluster communication
*/
public final class AFTIPCSocketAddress extends AFSocketAddress {
public static AFTIPCSocketAddress of(int type, int instance);
public static AFTIPCSocketAddress of(int type, int instance, int scope);
public int getType();
public int getInstance();
public int getScope();
}
/**
* VSOCK socket addressing for VM communication
*/
public final class AFVSOCKSocketAddress extends AFSocketAddress {
public static AFVSOCKSocketAddress of(int cid, int port);
public int getCID();
public int getPort();
}
/**
* AF_SYSTEM socket addressing for macOS system communication
*/
public final class AFSYSTEMSocketAddress extends AFSocketAddress {
public static AFSYSTEMSocketAddress of(int id);
public int getSystemID();
}Usage Examples for Other Address Types:
// TIPC addressing (Linux cluster communication)
AFTIPCSocketAddress tipcAddr = AFTIPCSocketAddress.of(1000, 1, 2);
System.out.println("TIPC - Type: " + tipcAddr.getType() +
", Instance: " + tipcAddr.getInstance() +
", Scope: " + tipcAddr.getScope());
// VSOCK addressing (VM communication)
AFVSOCKSocketAddress vsockAddr = AFVSOCKSocketAddress.of(2, 1234);
System.out.println("VSOCK - CID: " + vsockAddr.getCID() +
", Port: " + vsockAddr.getPort());
// AF_SYSTEM addressing (macOS system communication)
AFSYSTEMSocketAddress systemAddr = AFSYSTEMSocketAddress.of(1);
System.out.println("System ID: " + systemAddr.getSystemID());Efficient address object reuse using the built-in pooling system:
/**
* Object pool for socket addresses
*/
public class SocketAddressPool extends ObjectPool<AFSocketAddress> {
public static SocketAddressPool getInstance();
public AFSocketAddress acquire();
public void release(AFSocketAddress address);
}
/**
* Mutable socket address for efficient reuse
*/
public class MutableSocketAddress {
public void set(AFSocketAddress address);
public AFSocketAddress get();
public void clear();
}Usage Examples:
// Using address pool for high-frequency operations
SocketAddressPool pool = SocketAddressPool.getInstance();
// Acquire address from pool
AFSocketAddress pooledAddr = pool.acquire();
try {
// Use address for socket operations
AFUNIXSocket socket = AFUNIXSocket.connectTo((AFUNIXSocketAddress) pooledAddr);
// ... socket operations
} finally {
// Return to pool for reuse
pool.release(pooledAddr);
}
// Mutable address for dynamic addressing
MutableSocketAddress mutableAddr = new MutableSocketAddress();
for (int i = 0; i < 10; i++) {
AFUNIXSocketAddress addr = AFUNIXSocketAddress.of("/tmp/socket-" + i + ".sock");
mutableAddr.set(addr);
// Use mutable address
AFSocketAddress current = mutableAddr.get();
// ... address operations
mutableAddr.clear();
}// File system integration
public boolean exists();
public File getFile() throws FileNotFoundException;
public Path getPath() throws FileNotFoundException;
// Address properties
public boolean hasFilename();
public boolean isInAbstractNamespace();
public String getPathname();
public String getHostname();
// Binary representation
public byte[] getBytes();
public int getAddressFamily();Validation Examples:
AFUNIXSocketAddress addr = AFUNIXSocketAddress.of("/tmp/service.sock");
// Check if socket file exists
if (addr.exists()) {
System.out.println("Socket file exists at: " + addr.getFile());
} else {
System.out.println("Socket file does not exist, server may not be running");
}
// Address properties
System.out.println("Has filename: " + addr.hasFilename());
System.out.println("Pathname: " + addr.getPathname());
System.out.println("Is abstract: " + addr.isInAbstractNamespace());
// Binary representation for low-level operations
byte[] addressBytes = addr.getBytes();
int family = addr.getAddressFamily();
System.out.println("Address family: " + family);
System.out.println("Address bytes length: " + addressBytes.length);Linux-specific abstract namespace support for sockets not bound to filesystem:
// Create abstract socket (Linux only)
AFUNIXSocketAddress abstractAddr = AFUNIXSocketAddress.inAbstractNamespace("my-service");
// Check if in abstract namespace
if (abstractAddr.isInAbstractNamespace()) {
System.out.println("Using abstract namespace: " + abstractAddr.getPathname());
// Note: pathname will start with null byte for abstract sockets
}
// Abstract sockets don't have files
try {
File file = abstractAddr.getFile();
} catch (FileNotFoundException e) {
System.out.println("Abstract sockets don't have filesystem entries");
}Common addressing-related exceptions:
// Address creation failures
public class AFException extends IOException;
// File system related errors
public class FileNotFoundException extends IOException;
public class AddressUnavailableSocketException extends SocketException;Error Handling Examples:
try {
AFUNIXSocketAddress addr = AFUNIXSocketAddress.of("/invalid/path/socket.sock");
File socketFile = addr.getFile();
} catch (AFException e) {
System.err.println("Failed to create socket address: " + e.getMessage());
} catch (FileNotFoundException e) {
System.err.println("Socket file not found: " + e.getMessage());
}
// Validate directory exists before creating socket address
File socketDir = new File("/var/run/myapp");
if (!socketDir.exists()) {
if (!socketDir.mkdirs()) {
throw new IOException("Cannot create socket directory: " + socketDir);
}
}
File socketFile = new File(socketDir, "service.sock");
AFUNIXSocketAddress addr = AFUNIXSocketAddress.of(socketFile);Install with Tessl CLI
npx tessl i tessl/maven-com-kohlschutter-junixsocket--junixsocket-core