A simple, high-performance TCP server framework for Go.
- Simple API - Easy to use with functional options pattern
- Custom Codec - Pluggable message encoding/decoding via
io.Reader - Graceful Shutdown - Context-based cancellation support
- Heartbeat - Automatic read/write deadline management
- Error Handling - Flexible error handling with
DisconnectorContinueactions - Structured Logging - Built-in
slogintegration
- Go 1.23+
go get github.com/Zereker/socketpackage main
import (
"context"
"io"
"log"
"net"
"github.com/Zereker/socket"
)
// Define your message type
type Message struct {
Data []byte
}
func (m Message) Length() int { return len(m.Data) }
func (m Message) Body() []byte { return m.Data }
// Implement the Codec interface
type SimpleCodec struct{}
func (c *SimpleCodec) Decode(r io.Reader) (socket.Message, error) {
buf := make([]byte, 1024)
n, err := r.Read(buf)
if err != nil {
return nil, err
}
return Message{Data: buf[:n]}, nil
}
func (c *SimpleCodec) Encode(msg socket.Message) ([]byte, error) {
return msg.Body(), nil
}
// Implement the Handler interface
type EchoHandler struct{}
func (h *EchoHandler) Handle(tcpConn *net.TCPConn) {
conn, err := socket.NewConn(tcpConn,
socket.CustomCodecOption(&SimpleCodec{}),
socket.OnMessageOption(func(msg socket.Message) error {
// Echo the message back
return conn.Write(msg)
}),
)
if err != nil {
log.Printf("failed to create connection: %v", err)
return
}
conn.Run(context.Background())
}
func main() {
addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:8080")
server, err := socket.New(addr)
if err != nil {
log.Fatal(err)
}
log.Println("server listening on", addr)
server.Serve(context.Background(), &EchoHandler{})
}| Option | Description | Default |
|---|---|---|
CustomCodecOption(codec) |
Set message codec (required) | - |
OnMessageOption(handler) |
Set message handler (required) | - |
OnErrorOption(handler) |
Set error handler | Disconnect on error |
HeartbeatOption(duration) |
Set heartbeat interval | 30s |
BufferSizeOption(size) |
Set send channel buffer size | 1 |
MessageMaxSize(size) |
Set max message size | 1MB |
LoggerOption(logger) |
Set custom logger | slog default |
Control how errors are handled with OnErrorOption:
socket.OnErrorOption(func(err error) socket.ErrorAction {
if isTemporaryError(err) {
return socket.Continue // Suppress error and continue
}
return socket.Disconnect // Close the connection
})// Gracefully close the connection
conn.Close()
// Check if connection is closed
if conn.IsClosed() {
// Handle closed connection
}
// Get remote address
addr := conn.Addr()Three ways to send messages:
// Non-blocking write, returns ErrBufferFull if channel is full
conn.Write(msg)
// Blocking write with context cancellation
conn.WriteBlocking(ctx, msg)
// Write with timeout
conn.WriteTimeout(msg, 5*time.Second)All write methods return ErrConnectionClosed if the connection is closed.
Implement the Logger interface or use slog:
type Logger interface {
Debug(msg string, args ...any)
Info(msg string, args ...any)
Warn(msg string, args ...any)
Error(msg string, args ...any)
}MIT License - see LICENSE for details.