UIO (pronounced "ultra-IO") is a high-performance, event-driven networking framework for Go, designed for building scalable and efficient TCP/UDP servers and clients. It leverages modern I/O multiplexing techniques and provides a lightweight, non-blocking API for low-latency applications.
- 🚀 Event-Driven Architecture: Built on epoll/kqueue (Unix-like) for optimal I/O scheduling and
stdio
for others platform (Windows). - 🌐 Cross-Platform: Supports Linux, macOS, BSD variants, and Windows.
- 🔄 Protocol Support: TCP, TCP4/TCP6, UDP, UDP4/UDP6, Unix domain sockets.
- ⚡ Zero-Copy Optimizations: Batched read/write operations minimize memory copies.
- 🧩 Flexible Event Hooks:
OnOpen
,OnData
,OnClose
callbacks for connection lifecycle management. - 🔧 Tunable Parameters:
- Custom buffer sizes
- Write buffering thresholds
- Full/half-duplex modes
- SO_REUSEPORT support
go get github.com/urpc/uio
type Events struct {
// Pollers is set up to start the given number of event-loop goroutine.
// The default value is runtime.NumCPU().
Pollers int
// Addrs is the listening addr list for a server.
Addrs []string
// ReusePort indicates whether to set up the SO_REUSEPORT socket option.
// The default value is false.
ReusePort bool
// LockOSThread is used to determine whether each I/O event-loop is associated to an OS thread.
// The default value is false.
LockOSThread bool
// MaxBufferSize is the maximum number of bytes that can be read from the remote when the readable event comes.
// The default value is 4KB.
MaxBufferSize int
// WriteBufferedThreshold enabled when value is greater than 0, writes will go into the outbound buffer instead of attempting to send them out immediately,
// unless the outbound buffer reaches the threshold or the flush function is manually called.
//
// If you have multiple Write call requirements, opening it will improve write performance because it reduces the number of system calls by merging multiple write operations to improve performance.
// The default value is 0.
WriteBufferedThreshold int
// FullDuplex read events are always registered, which will improve program performance in most cases,
// unfortunately if there are malicious clients may deliberately slow to receive data will lead to server outbound buffer accumulation,
// in the absence of intervention may lead to service memory depletion.
// Turning this option off will change the event registration policy, readable events are unregistered if there is currently data waiting to be sent in the outbound buffer.
// Readable events are re-registered after the send buffer has been sent. In this case, network reads and writes will degenerate into half-duplex mode, ensuring that server memory is not exhausted.
// The default value is false.
FullDuplex bool
// OnOpen fires when a new connection has been opened.
OnOpen func(c Conn)
// OnData fires when a socket receives data from the remote.
OnData func(c Conn) error
// OnClose fires when a connection has been closed.
OnClose func(c Conn, err error)
// OnInbound when any bytes read by a socket, it triggers the inbound event.
OnInbound func(c Conn, readBytes int)
// OnOutbound when any bytes write to a socket, it triggers the outbound event.
OnOutbound func(c Conn, writeBytes int)
// OnStart it triggers on the server initialized.
OnStart func(ev *Events)
// OnStop it triggers on the server closed.
OnStop func(ev *Events)
}
Basic Echo Server
package main
import (
"fmt"
"github.com/urpc/uio"
)
func main() {
var events uio.Events
events.OnOpen = func(c uio.Conn) {
fmt.Println("connection opened:", c.RemoteAddr())
}
events.OnData = func(c uio.Conn) error {
_, err := c.WriteTo(c)
return err
}
events.OnClose = func(c uio.Conn, err error) {
fmt.Println("connection closed:", c.RemoteAddr())
}
if err := events.Serve(":9527"); nil != err {
fmt.Println("server exited with error:", err)
}
}
The repository released under version 2.0 of the Apache License.