Common Configurations
Single Client Reuse
Create a single client instance and reuse it for multiple commands:
public class RconManager {
private final RconClient client;
public RconManager(String host, int port, String password) {
this.client = RconClient.builder()
.host(host)
.port(port)
.password(password)
.build();
}
public String sendCommand(String command) {
RconResponse response = client.sendCommand(command);
return response.getResponse();
}
public void close() {
client.close();
}
}Connection Pool
For applications requiring multiple concurrent connections:
public class RconConnectionPool {
private final Queue<RconClient> pool = new LinkedList<>();
private final int maxSize;
public RconConnectionPool(String host, int port, String password, int maxSize) {
this.maxSize = maxSize;
for (int i = 0; i < maxSize; i++) {
pool.add(RconClient.builder()
.host(host)
.port(port)
.password(password)
.build());
}
}
public RconClient acquire() {
synchronized (pool) {
while (pool.isEmpty()) {
try {
pool.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted while waiting for connection", e);
}
}
return pool.remove();
}
}
public void release(RconClient client) {
synchronized (pool) {
if (pool.size() < maxSize) {
pool.add(client);
} else {
client.close();
}
pool.notifyAll();
}
}
}Retry Logic
Implement automatic retry on connection failures:
public class RetryableRconClient {
private final RconClient client;
private final int maxRetries;
public RetryableRconClient(RconClient client, int maxRetries) {
this.client = client;
this.maxRetries = maxRetries;
}
public RconResponse sendCommandWithRetry(String command) {
RconException lastException = null;
for (int attempt = 0; attempt <= maxRetries; attempt++) {
try {
return client.sendCommand(command);
} catch (RconConnectionException e) {
lastException = e;
if (attempt < maxRetries) {
try {
Thread.sleep(1000 * (attempt + 1)); // Exponential backoff
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted during retry", ie);
}
}
}
}
throw lastException;
}
}Custom Timeout
Set custom connection timeout for slow networks:
RconClient client = RconClient.builder()
.host("remote-server.example.com")
.port(25575)
.password("password")
.timeout(Duration.ofSeconds(30)) // 30 second timeout
.build();Color Code Handling
Use ISO-8859-1 charset to properly handle Minecraft color codes:
RconClient client = RconClient.builder()
.host("localhost")
.port(25575)
.password("password")
.charset(StandardCharsets.ISO_8859_1) // For color codes
.build();
RconResponse response = client.sendCommand("list");
String coloredOutput = response.getResponse();
// Color codes like §c[Server] will be preserved correctlyFragment Strategy Selection
Choose the appropriate fragment resolution strategy:
// Use ACTIVE_PROBE for most cases (default)
RconClient client = RconClient.builder()
.host("localhost")
.port(25575)
.password("password")
.fragmentStrategy(FragmentResolutionStrategy.ACTIVE_PROBE)
.build();
// Use TIMEOUT for servers that don't handle empty commands well
RconClient timeoutClient = RconClient.builder()
.host("localhost")
.port(25575)
.password("password")
.fragmentStrategy(FragmentResolutionStrategy.TIMEOUT)
.build();Logging
The RconClient automatically logs request/response pairs. Enable debug logging to see details:
<!-- Logback example -->
<configuration>
<logger name="io.cavarest.rcon" level="DEBUG"/>
</configuration>Async Batch Processing
Process multiple commands concurrently using the async API:
public class BatchCommandProcessor {
private final RconClient client;
private final ExecutorService executor;
public BatchCommandProcessor(RconClient client) {
this.client = client;
this.executor = Executors.newFixedThreadPool(5);
}
public List<String> processCommands(List<String> commands) {
List<CompletableFuture<String>> futures = commands.stream()
.map(cmd -> client.sendCommandAsync(cmd)
.thenApply(RconResponse::getResponse))
.toList();
CompletableFuture<Void> allOf = CompletableFuture.allOf(
futures.toArray(new CompletableFuture[0])
);
try {
allOf.get(30, TimeUnit.SECONDS);
} catch (Exception e) {
throw new RuntimeException("Batch processing failed", e);
}
return futures.stream()
.map(CompletableFuture::join)
.toList();
}
public void shutdown() {
executor.shutdown();
client.close();
}
}Next Steps
-
Advanced Topics - Learn advanced patterns
-
Fragment Resolution - Deep dive on strategies
-
API Reference - Complete API documentation