smart-socket: simple API, small core, built for custom protocols and high connection counts.
The problem with “just use Netty”
Netty is the default choice for high-performance networking in Java — and for good reason. It is mature, battle-tested, and has a huge ecosystem.
But it is also heavy.
If you only need:
- Long-lived TCP connections
- A custom binary or text protocol
- A small, understandable networking layer
…you often end up carrying a lot of concepts, classes, and configuration that you never use.
Java’s built-in AIO (NIO.2) looked promising as a simpler alternative. In practice, many teams found it limited under high connection counts: scheduling inefficiencies, higher memory cost per connection, and occasional stability issues under stress.
That gap is where smart-socket sits.
What is smart-socket?
smart-socket is an open-source Java framework that keeps an AIO-style programming model while reimplementing the underlying engine for better efficiency and reliability.
Core ideas:
-
Only two interfaces to implement:
Protocol<T>andMessageProcessor<T> - A very small, readable core (a few thousand lines)
- Buffer pooling aimed at large numbers of long-lived connections
- Explicit connection lifecycle events
- Optional plugins (SSL/TLS, idle detection, metrics, rate limiting, etc.)
It is not trying to replace Netty for every use case.
It is a focused tool when you want less complexity and tighter control over the transport layer.
Minimal API surface
1. Protocol — turn bytes into messages
public interface Protocol<T> {
T decode(ByteBuffer readBuffer, AioSession session);
}
Return null when the frame is incomplete (half-packet). That is the entire framing contract.
2. MessageProcessor — handle messages and lifecycle
public interface MessageProcessor<T> {
void process(AioSession session, T msg);
default void stateEvent(AioSession session, StateMachineEnum event, Throwable t) {
// NEW_SESSION, SESSION_CLOSED, DECODE_EXCEPTION, ...
}
}
3. Bootstrap
// Server
AioQuickServer server = new AioQuickServer(8888, new StringProtocol(), new EchoProcessor());
server.start();
// Client
AioQuickClient client = new AioQuickClient("localhost", 8888, new StringProtocol(), processor);
AioSession session = client.start();
Sending data is straightforward:
WriteBuffer wb = session.writeBuffer();
wb.writeInt(body.length);
wb.write(body);
wb.flush();
No channel pipelines, no bootstrap hierarchies, no codec chains required for the basic case.
A complete echo example
Protocol (length-prefixed UTF-8 string):
public class StringProtocol implements Protocol<String> {
@Override
public String decode(ByteBuffer buffer, AioSession session) {
if (buffer.remaining() < Integer.BYTES) {
return null;
}
buffer.mark();
int length = buffer.getInt();
if (length > buffer.remaining()) {
buffer.reset();
return null;
}
byte[] bytes = new byte[length];
buffer.get(bytes);
return new String(bytes, StandardCharsets.UTF_8);
}
}
Processor:
public class EchoProcessor implements MessageProcessor<String> {
@Override
public void process(AioSession session, String msg) {
byte[] body = msg.getBytes(StandardCharsets.UTF_8);
WriteBuffer wb = session.writeBuffer();
try {
wb.writeInt(body.length);
wb.write(body);
wb.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Server:
public class EchoServer {
public static void main(String[] args) throws Exception {
new AioQuickServer(8888, new StringProtocol(), new EchoProcessor()).start();
}
}
Maven dependency:
<dependency>
<groupId>io.github.smartboot.socket</groupId>
<artifactId>aio-pro</artifactId>
<version>2.1.3</version>
</dependency>
Design highlights
Enhanced AIO runtime
smart-socket presents an AIO-style API but uses a carefully tuned asynchronous implementation underneath. The goal is better scheduling behavior and lower overhead for typical server workloads with many concurrent connections, while keeping the programming model familiar.
Memory model
A page-based buffer pool (BufferPagePool + VirtualBuffer) reduces allocation pressure and supports sharing pools across servers/clients when needed. This matters when you hold tens or hundreds of thousands of long-lived connections.
Plugin chain
Cross-cutting concerns stay out of your business code:
| Plugin | Role |
|---|---|
| SslPlugin | TLS/SSL |
| IdleStatePlugin | Idle / heartbeat |
| MonitorPlugin | Metrics |
| RateLimiterPlugin | Traffic control |
| StreamMonitorPlugin | Byte-level monitoring |
| BufferPageMonitorPlugin | Pool visibility |
Extend AbstractMessageProcessor and call addPlugin(...).
Clear state machine
You get explicit callbacks for connection establishment, shutdown, decode/process errors, and accept rejection. That makes it easier to implement reconnect logic, metrics, and graceful close without guessing.
When to choose smart-socket
Good fit
- Custom binary or text protocols
- IM, IoT gateways, device management, internal RPC
- Long-lived TCP connections at scale
- Teams that want a small core they can actually read
- Resource-constrained or “keep the stack thin” environments
Probably not the best fit
- You need a full HTTP/WebSocket stack out of the box
- You rely heavily on Netty’s ecosystem of codecs and community handlers
- You want an application framework rather than a focused transport library
Ecosystem
smart-socket is used as the networking foundation for several projects:
- feat — lightweight high-performance Java web framework
- smart-mqtt — MQTT broker aimed at large-scale IoT
- Redisun — lightweight Redis client
- smart-servlet — Servlet container on the same core
If the framework can power MQTT brokers and web stacks, it is past the “toy project” stage.
Try it
- GitHub: https://github.com/smartboot/smart-socket
- Docs: https://smartboot.tech/smart-socket
- License: Apache 2.0
Feedback, issues, and contributions are welcome — especially from people building real long-connection services.
If you have been looking for something lighter than Netty for custom protocols and persistent connections, smart-socket is worth a weekend experiment.

Top comments (0)