One connection. Bidirectional RPC, acked messaging, and stream multiplexing — behind a single net.Conn.
You're building an IM server, a message queue, an API gateway, a reverse tunnel for NAT traversal, or a service-mesh sidecar. To get it right you need bidirectional RPC, reliable messaging with acks, many logical streams over one TCP connection, automatic reconnect, and all of it has to play nicely with Go's net.Conn / net.Listener.
The usual answer is: gRPC for RPC, yamux/smux for multiplexing, NATS or a custom protocol for messaging, and a tangle of glue to keep their lifecycles in sync. Geminio offers the whole bundle behind one interface.
| gRPC | yamux / smux | NATS | Geminio | |
|---|---|---|---|---|
| Request / response RPC | ✅ | — | — | ✅ |
| Server-initiated RPC to client | — | — | ✅ | |
| Messaging with publish/ack | — | — | ✅ | ✅ |
| Stream multiplexing | ✅ (HTTP/2) | ✅ | — | ✅ |
Drop-in net.Conn / net.Listener |
— | ✅ | — | ✅ |
| Client-side auto-reconnect | — | — | ✅ | ✅ |
| Single binary, no broker | ✅ | ✅ | — | ✅ |
"Server-initiated RPC" means the server can
Call("method", ...)a handler the client registered — not just push messages on an open stream. It's the piece most "RPC libraries" don't ship.
- 🔄 Bidirectional RPC — either side can register methods and call the other's.
- 📨 Acked messaging —
Publish/Receivewith delivery confirmation; sync and async. - 🔀 Stream multiplexing — open any number of logical streams over one connection.
- 🔌
net.Conn/net.Listenercompatible — streams drop into any code that speaks Go's net interfaces. - 🆔 Stable peer & stream IDs —
ClientIDandStreamIDmake routing, authz, and tracing straightforward. - 🔁 Auto-reconnect — client resumes transparently after network blips.
- ⚡ ~5 GB/s per-stream throughput and ~23K RPC round-trips/sec on a laptop-class CPU (see Benchmarks).
- 🧪 Hardened — unit, integration, e2e, stress, chaos, and regression test suites.
go get github.com/singchia/geminioEvery Geminio stream is a net.Conn, and every End is a net.Listener. So a server-initiated file transfer is just io.Copy — no framing, no codec, no broker.
Server — accept clients, open a stream back, copy the file in.
ln, _ := server.Listen("tcp", "127.0.0.1:8080")
for {
end, _ := ln.AcceptEnd()
go func() {
stream, _ := end.OpenStream()
defer stream.Close()
f, _ := os.Open("payload.bin")
defer f.Close()
io.Copy(stream, f)
}()
}Client — treat the End as a net.Listener, save each incoming stream.
end, _ := client.NewEnd("tcp", "127.0.0.1:8080")
defer end.Close()
for {
conn, _ := end.Accept()
f, _ := os.Create("received.bin")
io.Copy(f, conn)
f.Close()
conn.Close()
}The server initiates. The client listens on its own dial-out connection. io.Copy does the rest because the stream speaks net.Conn. Full runnable examples — RPC, bidirectional RPC, acked messaging, more multiplexing — in docs/USAGE.md.
| Scenario | Why Geminio fits | Example |
|---|---|---|
| NAT traversal / reverse tunnel | one outbound connection carries bidirectional control + many data streams | examples/traversal |
| Chatroom / IM | acked messaging, per-client IDs, auto-reconnect | examples/chatroom |
| Message queue | topics, ack, async publish | examples/mq |
| TCP relay / proxy | net.Conn-compatible streams over a control plane |
examples/relay |
| API gateway / sidecar | bidirectional RPC + multiplexing + client identity | build directly on End |
Three layers — Connection (physical TCP, heartbeat, FSM), Multiplexer / Dialogue (logical streams, routing, write scheduling), and Application (RPC and messaging semantics) — let Geminio ship one unified End while keeping each concern isolated and testable. Deep dive in docs/MULTIPLEXING.md.
Apple M4 (2024 laptop-class CPU):
BenchmarkMessage-10 235592 14600 ns/op 8977 MB/s 68495 ops/sec
BenchmarkEnd-10 137131 25537 ns/op 5132 MB/s 39159 ops/sec
BenchmarkStream-10 137937 25853 ns/op 5069 MB/s 38680 ops/sec
BenchmarkRPC-10 84450 42527 ns/op 3082 MB/s 23515 ops/sec
~39K streams/sec at 5 GB/s, ~23K RPC round-trips/sec at 3 GB/s, ~68K short-message ops/sec at 8.9 GB/s. Run make bench on your own box.
- Usage guide —
docs/USAGE.md - API reference — pkg.go.dev/github.com/singchia/geminio
- Runnable examples —
examples/ - Design deep dive —
docs/MULTIPLEXING.md - Roadmap —
ROADMAP.md
PRs and issues are welcome. See CONTRIBUTING.md. In short: one feature per PR, tests alongside code, run make test before submitting.
Apache 2.0 — © Austin Zhai, 2023–2030.
Made with OSS Insight

