Geminio
A hybrid application-layer networking framework with support for messaging, RPC, bidirectional RPC, multiplexing, and maintaining client-server consistency.
Install / Use
/learn @singchia/GeminioREADME
</div>A powerful application-layer network programming library for Go
📖 Introduction
Geminio is a comprehensive application-layer network programming library for Go, named after the Doubling Charm from Harry Potter. It provides a unified interface for building network applications with features like RPC, bidirectional RPC, messaging, multi-session management, connection multiplexing, and raw connection handling.
Geminio simplifies network development by abstracting away the complexity of low-level network programming, allowing developers to focus on business logic rather than connection management.
✨ Features
- 🔄 RPC & Bidirectional RPC - Full support for remote procedure calls with bidirectional capabilities
- 📨 Messaging - Reliable message delivery with acknowledgment guarantees
- 🔀 Connection Multiplexing - Multiple logical connections over a single physical connection
- 🆔 Connection Identification - Unique ClientID and StreamID for connection management
- 🔌 Native Compatibility - Seamless integration with Go's
net.Connandnet.Listener - 🔁 High Availability - Built-in automatic reconnection mechanism for clients
- ⚡ High Performance - Optimized for low latency and high throughput
- 🛡️ Production Ready - Extensive testing including stress tests, chaos tests, and performance profiling
- 📦 Zero Dependencies - Lightweight with minimal external dependencies
🚀 Quick Start
Installation
go get github.com/singchia/geminio
Basic Example
Server:
package main
import (
"context"
"log"
"github.com/singchia/geminio/server"
)
func main() {
ln, err := server.Listen("tcp", "127.0.0.1:8080")
if err != nil {
log.Fatal(err)
}
for {
end, err := ln.AcceptEnd()
if err != nil {
log.Fatal(err)
}
go func() {
msg, err := end.Receive(context.TODO())
if err != nil {
return
}
log.Printf("Received: %s", string(msg.Data()))
msg.Done()
}()
}
}
Client:
package main
import (
"context"
"log"
"github.com/singchia/geminio/client"
)
func main() {
end, err := client.NewEnd("tcp", "127.0.0.1:8080")
if err != nil {
log.Fatal(err)
}
defer end.Close()
msg := end.NewMessage([]byte("Hello, Geminio!"))
if err := end.Publish(context.TODO(), msg); err != nil {
log.Fatal(err)
}
}
📚 Documentation
Architecture
Geminio follows a layered architecture design:
<img src="./docs/biz-arch.png" width="100%">Core Interfaces
The library's main abstractions are defined in geminio.go:
// RPC interface
type RPCer interface {
NewRequest(data []byte, opts ...*options.NewRequestOptions) Request
Call(ctx context.Context, method string, req Request, opts ...*options.CallOptions) (Response, error)
CallAsync(ctx context.Context, method string, req Request, ch chan *Call, opts ...*options.CallOptions) (*Call, error)
Register(ctx context.Context, method string, rpc RPC) error
}
// Messaging interface
type Messager interface {
NewMessage(data []byte, opts ...*options.NewMessageOptions) Message
Publish(ctx context.Context, msg Message, opts ...*options.PublishOptions) error
PublishAsync(ctx context.Context, msg Message, ch chan *Publish, opts ...*options.PublishOptions) (*Publish, error)
Receive(ctx context.Context) (Message, error)
}
// Stream interface (combines RPC, Messaging, and Raw connection)
type Stream interface {
RawRPCMessager // RPC + Messaging + net.Conn
StreamID() uint64
ClientID() uint64
Meta() []byte
}
// Multiplexer for managing multiple streams
type Multiplexer interface {
OpenStream(opts ...*options.OpenStreamOptions) (Stream, error)
AcceptStream() (Stream, error)
ListStreams() []Stream
}
// End is the main entry point
type End interface {
Stream // End is also a default stream (streamID = 1)
Multiplexer // End can manage multiple streams
Close()
}
💡 Usage Examples
Message Publishing
Server:
package main
import (
"context"
"log"
"github.com/singchia/geminio/server"
)
func main() {
ln, err := server.Listen("tcp", "127.0.0.1:8080")
if err != nil {
log.Fatal(err)
}
for {
end, err := ln.AcceptEnd()
if err != nil {
log.Fatal(err)
}
go func() {
msg, err := end.Receive(context.TODO())
if err != nil {
return
}
log.Printf("Received: %s", string(msg.Data()))
msg.Done()
}()
}
}
Client:
package main
import (
"context"
"log"
"github.com/singchia/geminio/client"
)
func main() {
end, err := client.NewEnd("tcp", "127.0.0.1:8080")
if err != nil {
log.Fatal(err)
}
defer end.Close()
msg := end.NewMessage([]byte("hello"))
if err := end.Publish(context.TODO(), msg); err != nil {
log.Fatal(err)
}
}
RPC
Server:
package main
import (
"context"
"log"
"github.com/singchia/geminio"
"github.com/singchia/geminio/server"
)
func main() {
ln, err := server.Listen("tcp", "127.0.0.1:8080")
if err != nil {
log.Fatal(err)
}
for {
end, err := ln.AcceptEnd()
if err != nil {
log.Fatal(err)
}
go func() {
err := end.Register(context.TODO(), "echo", echo)
if err != nil {
log.Fatal(err)
}
}()
}
}
func echo(_ context.Context, req geminio.Request, rsp geminio.Response) {
rsp.SetData(req.Data())
log.Printf("Echo: %s", string(req.Data()))
}
Client:
package main
import (
"context"
"log"
"github.com/singchia/geminio/client"
)
func main() {
opt := client.NewEndOptions()
opt.SetWaitRemoteRPCs("echo")
end, err := client.NewEnd("tcp", "127.0.0.1:8080", opt)
if err != nil {
log.Fatal(err)
}
defer end.Close()
rsp, err := end.Call(context.TODO(), "echo", end.NewRequest([]byte("hello")))
if err != nil {
log.Fatal(err)
}
log.Printf("Response: %s", string(rsp.Data()))
}
Bidirectional RPC
Server:
package main
import (
"context"
"log"
"github.com/singchia/geminio"
"github.com/singchia/geminio/server"
)
func main() {
opt := server.NewEndOptions()
opt.SetWaitRemoteRPCs("client-echo")
opt.SetRegisterLocalRPCs(&geminio.MethodRPC{"server-echo", echo})
ln, err := server.Listen("tcp", "127.0.0.1:8080", opt)
if err != nil {
log.Fatal(err)
}
for {
end, err := ln.AcceptEnd()
if err != nil {
log.Fatal(err)
}
go func() {
rsp, err := end.Call(context.TODO(), "client-echo", end.NewRequest([]byte("foo")))
if err != nil {
log.Fatal(err)
}
log.Printf("Client echo: %s", string(rsp.Data()))
}()
}
}
func echo(_ context.Context, req geminio.Request, rsp geminio.Response) {
rsp.SetData(req.Data())
log.Printf("Server echo: %s", string(req.Data()))
}
Client:
package main
import (
"context"
"log"
"github.com/singchia/geminio"
"github.com/singchia/geminio/client"
)
func main() {
opt := client.NewEndOptions()
opt.SetWaitRemoteRPCs("server-echo")
opt.SetRegisterLocalRPCs(&geminio.MethodRPC{"client-echo", echo})
end, err := client.NewEnd("tcp", "127.0.0.1:8080", opt)
if err != nil {
log.Fatal(err)
}
defer end.Close()
rsp, err := end.Call(context.TODO(), "server-echo", end.NewRequest([]byte("bar")))
if err != nil {
log.Fatal(err)
}
log.Printf("Server echo: %s", string(rsp.Data()))
}
func echo(_ context.Context, req geminio.Request, rsp geminio.Response) {
rsp.SetData(req.Data())
log.Printf("Client echo: %s", string(req.Data()))
}
Multiplexing
Server:
package main
import (
"log"
"github.com/singchia/geminio/server"
)
func main() {
ln, err := server.Listen("tcp", "127.0.0.1:8080")
if err != nil {
log.Fatal(err)
}
for {
end, err := ln.AcceptEnd()
if err != nil {
log.Fatal(err)
}
// Open stream #1
sm1, err := end.OpenStream()
if err != nil {
log.Fatal(err)
}
sm1.Write([]byte("hello#1"))
sm1.Close()
// Open stream #2
sm2, err := end.OpenStream()
if err != nil {
log.Fatal(err)
}
sm2.Write([]byte("hello#2"))
sm2.Close()
}
}
Client:
package main
import (
"net"
"log"
"github.com/singchia/geminio/client"
)
func main() {
end, err := client.NewEnd("tcp", "127.0.0.1:8080")
if err != nil {
log.Fatal(err)
}
defer end.Close()
// End can be used as net.Listener
ln := net.Listener(end)
for {
conn, err := ln.Accept()
if err != ni
Related Skills
openhue
339.3kControl Philips Hue lights and scenes via the OpenHue CLI.
sag
339.3kElevenLabs text-to-speech with mac-style say UX.
weather
339.3kGet current weather and forecasts via wttr.in or Open-Meteo
tweakcc
1.5kCustomize Claude Code's system prompts, create custom toolsets, input pattern highlighters, themes/thinking verbs/spinners, customize input box & user message styling, support AGENTS.md, unlock private/unreleased features, and much more. Supports both native/npm installs on all platforms.
