A lightweight, event-driven WebSocket communication library built with Netty for Java 8+.
repositories {
maven("https://maven.afterlike.org/releases")
}
dependencies {
implementation("org.afterlike:irclib:1.0")
}repositories {
maven { url 'https://maven.afterlike.org/releases' }
}
dependencies {
implementation 'org.afterlike:irclib:1.0'
}<repositories>
<repository>
<id>afterlike</id>
<url>https://maven.afterlike.org/releases</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.afterlike</groupId>
<artifactId>irclib</artifactId>
<version>1.0</version>
</dependency>
</dependencies>- WebSocket Transport: Full WebSocket support with automatic SSL/TLS for
wss://URIs - Binary Protocol: Efficient packet-based communication with type-safe encoding/decoding
- Auto-Reconnection: Configurable automatic reconnection with connection state tracking
- Keepalive: Built-in idle detection with WebSocket ping/pong frames
- Thread-Safe: Proper synchronization for concurrent access
- Event-Driven: Clean callback-based API for handling messages and connection events
import org.afterlike.irclib.client.IRCClientBuilder;
import org.afterlike.irclib.client.IRCClient;
import org.afterlike.irclib.client.ClientEventAdapter;
import java.net.URI;
IRCClient client = new IRCClientBuilder(new URI("wss://your-server.com:443"))
.eventHandler(new ClientEventAdapter() {
@Override
public void onConnect() {
System.out.println("Connected!");
}
@Override
public void onReceiveMessage(String author, String color, String client, String message) {
System.out.println(author + ": " + message);
}
})
.defaultExecutor()
.buildAndAwaitConnection();
// Send a message
client.sendMessage("MyUsername", "Hello, world!");
// Check connection state
if (client.isConnected()) {
System.out.println("State: " + client.getState());
}
// Graceful shutdown
client.close();import org.afterlike.irclib.server.IRCServerBuilder;
import org.afterlike.irclib.server.IRCServer;
import java.net.URI;
IRCServer server = new IRCServerBuilder(new URI("ws://0.0.0.0:8080"))
.eventHandler((username, message) -> {
System.out.println("Received from " + username + ": " + message);
// Broadcast to all connected clients
server.broadcastMessage(username, message);
})
.build();
// Start listening (blocking)
server.listen();
// Or close when done
server.close();| Class | Description |
|---|---|
IRCClientBuilder |
Fluent builder for creating IRC clients |
IRCClient |
WebSocket client with auto-reconnection |
IClientEventHandler |
Interface for handling client events |
ClientEventAdapter |
Abstract adapter with empty default implementations |
ConnectionState |
Enum: DISCONNECTED, CONNECTING, CONNECTED, RECONNECTING, CLOSED |
| Method | Description |
|---|---|
sendMessage(username, message) |
Send a chat message |
isConnected() |
Check if currently connected |
getState() |
Get current ConnectionState |
close() |
Close connection and stop reconnection |
| Class | Description |
|---|---|
IRCServerBuilder |
Fluent builder for creating IRC servers |
IRCServer |
WebSocket server managing multiple clients |
IServerEventHandler |
Interface for handling incoming messages |
| Method | Description |
|---|---|
broadcastMessage(username, message) |
Send message to all clients |
broadcastUserChange(user, isJoin) |
Notify clients of user join/leave |
listen() |
Start listening (blocking) |
close() |
Stop server and disconnect all clients |
All packets use a binary format with a 1-byte packet ID followed by packet-specific data:
+----------+------------------+
| Packet ID | Packet Data |
| (1 byte) | (variable) |
+----------+------------------+
Strings are encoded as length-prefixed UTF-8:
+----------+------------------+
| Length | UTF-8 Bytes |
| (4 bytes)| (variable) |
+----------+------------------+
| ID | Name | Direction | Fields |
|---|---|---|---|
0x00 |
Reserved | - | (empty) |
0x01 |
Message | Server → Client | author, clientColor, client, message |
0x02 |
UserChange | Server → Client | user, clientColor, client, join (boolean) |
0x03 |
Message | Client → Server | username, message |
| Limit | Value |
|---|---|
| Max string length | 64 KB |
| Max HTTP aggregate | 8 KB |
| Connection timeout | 30 seconds |
| Reader idle timeout | 60 seconds |
| Writer idle timeout | 30 seconds |
The server loads client metadata from files matching client.* in the working directory:
client.production
client.testing
Format (pipe-delimited):
<identifier>|<color>|<name>
Example:
1|#FF5733|ProductionClient
2|#33FF57|TestClient
DISCONNECTED ──► CONNECTING ──► CONNECTED
▲ │
│ ▼
└────── RECONNECTING ◄────────┘
│
▼
CLOSED
- DISCONNECTED: Initial state or connection lost
- CONNECTING: Establishing initial connection
- CONNECTED: Successfully connected and ready
- RECONNECTING: Lost connection, attempting to reconnect
- CLOSED: Explicitly closed, will not reconnect
IRCClient: Thread-safe forsendMessage(),close(), state queriesIRCServer: Thread-safe forbroadcast*(),addChannel(),removeChannel(),close()- Event handlers are called from Netty's event loop threads
./gradlew buildRun tests:
./gradlew testCreate fat JAR:
./gradlew fatJarPublish to Maven:
./gradlew publish- Java 8+ (compile target)
- Gradle 8.x with Java 17+ (build tool runtime)
See LICENSE file for details.