socket

package
v1.19.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 4, 2026 License: MIT Imports: 5 Imported by: 0

README

Socket Package

License Go Version Coverage

Unified, production-ready socket communication framework for TCP, UDP, and Unix domain sockets with optional TLS encryption, comprehensive configuration, and platform-aware protocol selection.


Table of Contents


Overview

The socket package provides a comprehensive, production-ready framework for network socket communication in Go. It offers unified interfaces for both client and server implementations across multiple protocols (TCP, UDP, Unix domain sockets) with optional TLS encryption, automatic platform detection, and comprehensive error handling.

This package serves as the foundation for all socket-based communication in golib, providing platform-aware abstractions that work seamlessly across different network protocols and operating systems.

Design Philosophy
  1. Unified Interface: All socket types implement common interfaces (Server, Client, Context)
  2. Platform Awareness: Automatic protocol availability based on operating system
  3. Type Safety: Configuration-driven construction with compile-time validation
  4. Performance First: Zero-copy operations and minimal allocations where possible
  5. Production Ready: Built-in error handling, logging, and monitoring capabilities
  6. Concurrent by Design: Thread-safe operations with atomic state management
  7. Standard Compliance: Implements io.Reader, io.Writer, io.Closer, context.Context
Key Features
  • Multiple Protocols: TCP, UDP, Unix domain sockets, Unix datagrams
  • TLS/SSL Support: Optional encryption for TCP connections
  • Platform-Aware: Automatic Unix socket support on Linux/Darwin
  • Unified API: Consistent interface across all protocols
  • Configuration Builders: Type-safe configuration with validation
  • Connection Monitoring: State tracking and event callbacks
  • Error Handling: Comprehensive error propagation and filtering
  • Context Integration: Full support for Go's context.Context
  • Resource Management: Automatic cleanup and graceful shutdown
  • High Performance: Optimized for concurrent, high-throughput scenarios

Architecture

Package Structure
socket/                           # Core interfaces and types
├── interface.go                  # Server, Client interfaces
├── context.go                    # Context interface
├── doc.go                        # Package documentation
├── example_test.go               # Example tests
├── socket_test.go                # Unit tests
│
├── config/                       # Configuration and validation
│   ├── client.go                 # Client configuration
│   ├── server.go                 # Server configuration
│   └── validator.go              # Validation logic
│
├── client/                       # Client factory and implementations
│   ├── interface.go              # Factory (New)
│   ├── tcp/                      # TCP client
│   ├── udp/                      # UDP client
│   ├── unix/                     # Unix socket client (Linux/Darwin)
│   └── unixgram/                 # Unix datagram client (Linux/Darwin)
│
└── server/                       # Server factory and implementations
    ├── interface.go              # Factory (New)
    ├── tcp/                      # TCP server
    ├── udp/                      # UDP server
    ├── unix/                     # Unix socket server (Linux/Darwin)
    └── unixgram/                 # Unix datagram server (Linux/Darwin)
Component Diagram
┌────────────────────────────────────────────────────────────────────┐
│                       socket Package                               │
│                  (Core Interfaces & Types)                         │
├────────────────────────────────────────────────────────────────────┤
│                                                                    │
│  ┌──────────────────────────────────────────────────────────┐      │
│  │             Core Interfaces                              │      │
│  │  • Server   - Server operations                          │      │
│  │  • Client   - Client operations                          │      │
│  │  • Context  - Connection context                         │      │
│  └──────────────────────────────────────────────────────────┘      │
│                                                                    │
│  ┌──────────────────────────────────────────────────────────┐      │
│  │             Core Types                                   │      │
│  │  • ConnState       - Connection state tracking           │      │
│  │  • HandlerFunc     - Request handler                     │      │
│  │  • FuncError       - Error callback                      │      │
│  │  • FuncInfo        - Connection info callback            │      │
│  └──────────────────────────────────────────────────────────┘      │
│                                                                    │
└─────┬──────────────────────────────────────────────────┬───────────┘
      │                                                  │
      ▼                                                  ▼
┌───────────────────────┐                   ┌───────────────────────┐
│   client Package      │                   │   server Package      │
│   (Client Factory)    │                   │   (Server Factory)    │
├───────────────────────┤                   ├───────────────────────┤
│ • TCP Client          │                   │ • TCP Server          │
│ • UDP Client          │                   │ • UDP Server          │
│ • Unix Client         │                   │ • Unix Server         │
│ • UnixGram Client     │                   │ • UnixGram Server     │
└───────────────────────┘                   └───────────────────────┘
              │                                       │
              └───────────────┬───────────────────────┘
                              │
                    ┌─────────▼─────────┐
                    │   config Package  │
                    │  (Configuration)  │
                    ├───────────────────┤
                    │ • Client Config   │
                    │ • Server Config   │
                    │ • Validation      │
                    └───────────────────┘
Protocol Selection

The package automatically selects the appropriate implementation based on protocol type:

┌─────────────────────┬──────────────────┬─────────────────────┐
│  Protocol Value     │  Platform        │  Implementation     │
├─────────────────────┼──────────────────┼─────────────────────┤
│  NetworkTCP         │  All             │  tcp/*              │
│  NetworkTCP4        │  All             │  tcp/*              │
│  NetworkTCP6        │  All             │  tcp/*              │
│  NetworkUDP         │  All             │  udp/*              │
│  NetworkUDP4        │  All             │  udp/*              │
│  NetworkUDP6        │  All             │  udp/*              │
│  NetworkUnix        │  Linux/Darwin    │  unix/*             │
│  NetworkUnixGram    │  Linux/Darwin    │  unixgram/*         │
│  Other values       │  All             │  ErrInvalidProtocol │
└─────────────────────┴──────────────────┴─────────────────────┘

Performance

Protocol Comparison
Protocol Throughput Latency Best For Platform
TCP High Low Network IPC, reliability All
UDP Very High Very Low Datagrams, speed All
Unix Highest Lowest Local IPC, performance Linux/Darwin
UnixGram Highest Lowest Local datagrams Linux/Darwin
Benchmarks

Based on actual test execution:

Operation Time Notes
Factory Overhead <1µs Negligible
TCP Connection ~1-5ms Network-dependent
UDP Connection ~0ms Connectionless
Unix Connection ~35µs Fastest
Read/Write ~100µs Protocol-dependent
State Tracking <1µs Atomic operations

Interface Operations:

Operation Throughput Latency
ConnState.String() N/A <10ns
ErrorFilter() N/A <50ns
Context methods N/A <100ns
Scalability
  • Concurrent Connections: Tested with 1000+ concurrent connections
  • Factory Calls: Thread-safe, tested with 100 concurrent goroutines
  • Memory per Connection: ~32KB (configurable buffer)
  • Zero Race Conditions: All tests pass with -race detector

Subpackages

client

Purpose: Unified factory for creating socket clients across protocols.

Key Features:

  • Single entry point (New) for all protocols
  • Platform-aware protocol selection
  • TLS support for TCP
  • Type-safe configuration

Performance: <1µs factory overhead

Coverage: 81.2%

Documentation: client/README.md


server

Purpose: Unified factory for creating socket servers across protocols.

Key Features:

  • Single entry point (New) for all protocols
  • Platform-aware protocol selection
  • TLS support for TCP servers
  • Graceful shutdown
  • Connection tracking

Performance: <1µs factory overhead

Coverage: 100.0%

Documentation: server/README.md


config

Purpose: Configuration structures and validation for clients and servers.

Key Features:

  • Declarative configuration API
  • Comprehensive validation
  • Platform compatibility checks
  • TLS configuration support
  • Unix socket permissions

Performance: <1ms validation

Coverage: 89.4%

Documentation: config/README.md


Use Cases

1. TCP Server with TLS

Problem: Secure network service with encrypted connections.

import (
    "github.com/nabbar/golib/socket/config"
    "github.com/nabbar/golib/socket/server"
)

cfg := config.Server{
    Network: protocol.NetworkTCP,
    Address: ":443",
    TLS: config.ServerTLS{
        Enabled: true,
    },
}

srv, err := server.New(nil, handleRequest, cfg)
if err != nil {
    log.Fatal(err)
}
defer srv.Close()

ctx := context.Background()
srv.Listen(ctx)

Real-world: HTTPS servers, secure APIs, encrypted microservices.

2. High-Performance Local IPC

Problem: Fast inter-process communication on same host.

cfg := config.Server{
    Network:   protocol.NetworkUnix,
    Address:   "/tmp/app.sock",
    PermFile:  0660,
}

srv, err := server.New(nil, handleRequest, cfg)
if err == config.ErrInvalidProtocol {
    // Fall back to TCP on Windows
    cfg.Network = protocol.NetworkTCP
    cfg.Address = ":8080"
    srv, err = server.New(nil, handleRequest, cfg)
}

Real-world: Database connections, microservices on same host, container communication.

3. Real-Time Metrics Collection

Problem: Low-latency metrics and monitoring data collection.

cfg := config.Server{
    Network: protocol.NetworkUDP,
    Address: ":9000",
}

srv, err := server.New(nil, handleMetrics, cfg)

Real-world: StatsD-like metrics, monitoring agents, real-time logging.

4. Multi-Protocol Service

Problem: Service accessible via multiple protocols simultaneously.

// Network access via TCP
tcpSrv, _ := server.New(nil, handler, config.Server{
    Network: protocol.NetworkTCP,
    Address: ":8080",
})

// Local access via Unix socket
unixSrv, _ := server.New(nil, handler, config.Server{
    Network: protocol.NetworkUnix,
    Address: "/tmp/app.sock",
})

// Start both
go tcpSrv.Listen(ctx)
go unixSrv.Listen(ctx)

Real-world: Database servers, cache services, message brokers.


Quick Start

Installation
go get github.com/nabbar/golib/socket
Basic TCP Server
package main

import (
    "context"
    "log"
    
    libsck "github.com/nabbar/golib/socket"
    libptc "github.com/nabbar/golib/network/protocol"
    sckcfg "github.com/nabbar/golib/socket/config"
    scksrv "github.com/nabbar/golib/socket/server"
)

func main() {
    // Define handler
    handler := func(ctx libsck.Context) {
        buf := make([]byte, 1024)
        n, _ := ctx.Read(buf)
        
        response := []byte("Echo: " + string(buf[:n]))
        ctx.Write(response)
    }
    
    // Create configuration
    cfg := sckcfg.Server{
        Network: libptc.NetworkTCP,
        Address: ":8080",
    }
    
    // Create server
    srv, err := scksrv.New(nil, handler, cfg)
    if err != nil {
        log.Fatal(err)
    }
    defer srv.Close()
    
    // Start listening
    log.Println("Server listening on :8080")
    ctx := context.Background()
    if err := srv.Listen(ctx); err != nil {
        log.Fatal(err)
    }
}
Basic TCP Client
package main

import (
    "context"
    "log"
    
    libptc "github.com/nabbar/golib/network/protocol"
    sckcfg "github.com/nabbar/golib/socket/config"
    sckclt "github.com/nabbar/golib/socket/client"
)

func main() {
    // Create configuration
    cfg := sckcfg.Client{
        Network: libptc.NetworkTCP,
        Address: "localhost:8080",
    }
    
    // Create client
    cli, err := sckclt.New(cfg, nil)
    if err != nil {
        log.Fatal(err)
    }
    defer cli.Close()
    
    // Connect
    ctx := context.Background()
    if err := cli.Connect(ctx); err != nil {
        log.Fatal(err)
    }
    
    // Send message
    _, err = cli.Write([]byte("Hello, server!"))
    if err != nil {
        log.Fatal(err)
    }
    
    // Read response
    buf := make([]byte, 1024)
    n, err := cli.Read(buf)
    if err != nil {
        log.Fatal(err)
    }
    
    log.Printf("Response: %s", buf[:n])
}
Unix Socket Server

Linux/Darwin only:

cfg := sckcfg.Server{
    Network:   libptc.NetworkUnix,
    Address:   "/tmp/app.sock",
    PermFile:  0660,
    GroupPerm: -1,
}

srv, err := scksrv.New(nil, handler, cfg)
if err != nil {
    if err == sckcfg.ErrInvalidProtocol {
        log.Fatal("Unix sockets not supported on this platform")
    }
    log.Fatal(err)
}
defer srv.Close()

ctx := context.Background()
srv.Listen(ctx)
UDP Server
handler := func(ctx libsck.Context) {
    buf := make([]byte, 65536)
    n, _ := ctx.Read(buf)
    log.Printf("Received datagram from %s: %s", ctx.RemoteHost(), buf[:n])
}

cfg := sckcfg.Server{
    Network: libptc.NetworkUDP,
    Address: ":9000",
}

srv, _ := scksrv.New(nil, handler, cfg)
defer srv.Close()

ctx := context.Background()
srv.Listen(ctx)

Best Practices

✅ DO

Choose Appropriate Protocol:

// Network communication → TCP (reliable)
cfg.Network = protocol.NetworkTCP

// Local IPC → Unix sockets (fastest)
cfg.Network = protocol.NetworkUnix

// Datagrams → UDP (lowest latency)
cfg.Network = protocol.NetworkUDP

Resource Management:

// Always close resources
srv, err := server.New(nil, handler, cfg)
if err != nil {
    return err
}
defer srv.Close()  // Ensure cleanup

Context Usage:

// Use context for lifecycle control
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

err := srv.Listen(ctx)

Error Handling:

// Filter expected errors
srv.RegisterFuncError(func(errs ...error) {
    for _, err := range errs {
        if err := socket.ErrorFilter(err); err != nil {
            log.Printf("Error: %v", err)
        }
    }
})

Platform Compatibility:

// Handle platform-specific protocols
cli, err := client.New(cfg, nil)
if err == config.ErrInvalidProtocol {
    // Fall back to TCP on unsupported platforms
    cfg.Network = protocol.NetworkTCP
    cli, err = client.New(cfg, nil)
}
❌ DON'T

Don't ignore protocol errors:

// ❌ BAD: Ignoring errors
cli, _ := client.New(cfg, nil)

// ✅ GOOD: Check errors
cli, err := client.New(cfg, nil)
if err != nil {
    return err
}

Don't leave resources open:

// ❌ BAD: No cleanup
srv, _ := server.New(nil, handler, cfg)

// ✅ GOOD: Always defer Close
defer srv.Close()

Don't assume platform support:

// ❌ BAD: Assuming Unix sockets available
cfg.Network = protocol.NetworkUnix
srv, _ := server.New(nil, handler, cfg)  // Fails on Windows

// ✅ GOOD: Check platform or handle errors
if err != nil && err == config.ErrInvalidProtocol {
    // Handle unsupported protocol
}

API Reference

Core Interfaces

Server Interface:

type Server interface {
    io.Closer
    RegisterFuncError(f FuncError)
    RegisterFuncInfo(f FuncInfo)
    RegisterFuncInfoServer(f FuncInfoSrv)
    SetTLS(enable bool, config TLSConfig) error
    Listen(ctx context.Context) error
    Listener() (network NetworkProtocol, listener string, tls bool)
    Shutdown(ctx context.Context) error
    IsRunning() bool
    IsGone() bool
    OpenConnections() int64
}

Client Interface:

type Client interface {
    io.ReadWriteCloser
    SetTLS(enable bool, config TLSConfig, serverName string) error
    RegisterFuncError(f FuncError)
    RegisterFuncInfo(f FuncInfo)
    Connect(ctx context.Context) error
    IsConnected() bool
    Once(ctx context.Context, request io.Reader, fct Response) error
}

Context Interface:

type Context interface {
    context.Context  // Deadline, Done, Err, Value
    io.Reader        // Read from connection
    io.Writer        // Write to connection
    io.Closer        // Close connection
    IsConnected() bool
    RemoteHost() string
    LocalHost() string
}
Connection States
const (
    ConnectionDial       // Client dialing
    ConnectionNew        // New connection
    ConnectionRead       // Reading data
    ConnectionCloseRead  // Closing read
    ConnectionHandler    // Handler executing
    ConnectionWrite      // Writing data
    ConnectionCloseWrite // Closing write
    ConnectionClose      // Closing connection
)
Error Handling
// ErrorFilter removes expected network errors
func ErrorFilter(err error) error

Usage:

if err := socket.ErrorFilter(err); err != nil {
    // Handle unexpected error
}

Contributing

Contributions are welcome! Please follow these guidelines:

  1. Code Quality

    • Follow Go best practices and idioms
    • Maintain or improve code coverage (target: >80%)
    • Pass all tests including race detector
    • Use gofmt and golint
  2. AI Usage Policy

    • AI must NEVER be used to generate package code or core functionality
    • AI assistance is limited to:
      • Testing (writing and improving tests)
      • Debugging (troubleshooting and bug resolution)
      • Documentation (comments, README, TESTING.md)
    • All AI-assisted work must be reviewed and validated by humans
  3. Testing

    • Add tests for new features
    • Use Ginkgo v2 / Gomega for test framework
    • Ensure zero race conditions
    • Maintain coverage above 80%
  4. Documentation

    • Update GoDoc comments for public APIs
    • Add examples for new features
    • Update README.md and TESTING.md if needed
  5. Pull Request Process

    • Fork the repository
    • Create a feature branch
    • Write clear commit messages
    • Ensure all tests pass
    • Update documentation
    • Submit PR with description of changes

Improvements & Security

Current Status

The package is production-ready with no urgent improvements or security vulnerabilities identified.

Code Quality Metrics
  • 100% test coverage for root package (target: >80%)
  • 90.3% average coverage across all subpackages
  • Zero race conditions detected with -race flag
  • Thread-safe implementations throughout
  • Memory-safe with proper resource cleanup
  • Standard interfaces for maximum compatibility
Future Enhancements (Non-urgent)

The following enhancements could be considered for future versions:

New Features:

  1. WebSocket support (ws/wss protocols)
  2. QUIC protocol support (HTTP/3)
  3. Connection pooling utilities
  4. Load balancing abstractions

Performance Optimizations:

  1. Zero-copy operations where possible
  2. Memory pooling for buffers
  3. SIMD optimizations for checksums
  4. io_uring support on Linux

Monitoring Enhancements:

  1. Prometheus metrics integration
  2. OpenTelemetry tracing
  3. Connection analytics
  4. Performance profiling hooks

These are optional improvements and not required for production use. The current implementation is stable, performant, and feature-complete for its intended use cases.


Resources

Package Documentation
  • GoDoc - Complete API reference with function signatures, method descriptions, and runnable examples.

  • doc.go - In-depth package documentation including design philosophy, architecture diagrams, protocol selection guide, and best practices for production use.

  • TESTING.md - Comprehensive test suite documentation covering test architecture, BDD methodology with Ginkgo v2, coverage analysis (100%), and guidelines for writing new tests.

Subpackage Documentation
  • client/README.md - Client factory documentation and protocol-specific client implementations
  • server/README.md - Server factory documentation and protocol-specific server implementations
  • config/README.md - Configuration structures, validation, and best practices
External References
  • Go net Package - Standard library networking primitives underlying all socket implementations.

  • Effective Go - Official Go programming guide covering best practices for concurrency, error handling, and interface design.

  • Unix Network Programming - Classic reference on socket programming concepts and patterns.


AI Transparency

In compliance with EU AI Act Article 50.4: AI assistance was used for testing, documentation, and bug resolution under human supervision. All core functionality is human-designed and validated.


License

MIT License - See LICENSE file for details.

Copyright (c) 2022 Nicolas JUHEL


Maintained by: Nicolas JUHEL
Package: github.com/nabbar/golib/socket
Version: See releases for versioning

Documentation

Overview

Package socket provides a unified, production-ready framework for network socket communication across multiple protocols and platforms. It offers consistent interfaces for both client and server implementations, supporting TCP, UDP, and Unix domain sockets with optional TLS encryption.

Overview

The socket package serves as the foundation for all socket-based communication in golib, providing platform-aware abstractions that work seamlessly across different network protocols and operating systems. It is designed for high-performance, concurrent applications requiring reliable socket communication with minimal boilerplate.

This package defines the core interfaces, types, and constants that are implemented by the specialized sub-packages for different protocols and operation modes.

Design Philosophy

  1. Unified Interface: All socket types implement common interfaces (Server, Client, Context)
  2. Platform Awareness: Automatic protocol availability based on operating system
  3. Type Safety: Configuration-driven construction with compile-time validation
  4. Performance First: Zero-copy operations and minimal allocations where possible
  5. Production Ready: Built-in error handling, logging, and monitoring capabilities
  6. Concurrent by Design: Thread-safe operations with atomic state management
  7. Standard Compliance: Implements io.Reader, io.Writer, io.Closer, context.Context

Architecture

## Package Structure

socket/                           # Core interfaces and types (this package)
├── interface.go                  # Server, Client, Context interfaces
├── context.go                    # Context interface definition
├── doc.go                        # Package documentation
│
├── config/                       # Configuration builders and validators
│   ├── builder_client.go         # Client configuration builder
│   ├── builder_server.go         # Server configuration builder
│   └── validator.go              # Configuration validation
│
├── client/                       # Client factory and implementations
│   ├── interface.go              # Factory method (New)
│   ├── tcp/                      # TCP client implementation
│   ├── udp/                      # UDP client implementation
│   ├── unix/                     # Unix socket client (Linux/Darwin)
│   └── unixgram/                 # Unix datagram client (Linux/Darwin)
│
└── server/                       # Server factory and implementations
    ├── interface.go              # Factory method (New)
    ├── tcp/                      # TCP server implementation
    ├── udp/                      # UDP server implementation
    ├── unix/                     # Unix socket server (Linux/Darwin)
    └── unixgram/                 # Unix datagram server (Linux/Darwin)

## Component Diagram

┌────────────────────────────────────────────────────────────────────┐
│                       socket Package                               │
│                  (Core Interfaces & Types)                         │
├────────────────────────────────────────────────────────────────────┤
│                                                                    │
│  ┌──────────────────────────────────────────────────────────┐      │
│  │             Core Interfaces                              │      │
│  │  • Server   - Server operations                          │      │
│  │  • Client   - Client operations                          │      │
│  │  • Context  - Connection context                         │      │
│  └──────────────────────────────────────────────────────────┘      │
│                                                                    │
│  ┌──────────────────────────────────────────────────────────┐      │
│  │             Core Types                                   │      │
│  │  • ConnState       - Connection state tracking           │      │
│  │  • HandlerFunc     - Request handler                     │      │
│  │  • FuncError       - Error callback                      │      │
│  │  • FuncInfo        - Connection info callback            │      │
│  └──────────────────────────────────────────────────────────┘      │
│                                                                    │
└─────┬──────────────────────────────────────────────────┬───────────┘
      │                                                  │
      ▼                                                  ▼
┌───────────────────────┐                   ┌───────────────────────┐
│   client Package      │                   │   server Package      │
│   (Client Factory)    │                   │   (Server Factory)    │
├───────────────────────┤                   ├───────────────────────┤
│ • TCP Client          │                   │ • TCP Server          │
│ • UDP Client          │                   │ • UDP Server          │
│ • Unix Client         │                   │ • Unix Server         │
│ • UnixGram Client     │                   │ • UnixGram Server     │
└───────────────────────┘                   └───────────────────────┘

## Data Flow

### Server Connection Flow

Listen → Accept → Handler → Read/Write → Close
   │        │        │          │           │
   │        │        │          │           └─→ ConnectionClose
   │        │        │          ├─→ ConnectionRead
   │        │        │          └─→ ConnectionWrite
   │        │        └─→ ConnectionHandler
   │        └─→ ConnectionNew
   └─→ Server Start

### Client Connection Flow

Connect → Read/Write → Close
   │          │          │
   │          │          └─→ ConnectionClose
   │          ├─→ ConnectionRead
   │          └─→ ConnectionWrite
   └─→ ConnectionDial

Key Features

  • Multiple Protocol Support: TCP, UDP, Unix domain sockets, Unix datagrams
  • TLS/SSL Encryption: Optional TLS for TCP connections
  • Platform-Aware: Automatic Unix socket support on Linux/Darwin
  • Unified API: Consistent interface across all protocols
  • Configuration Builders: Type-safe configuration with validation
  • Connection Monitoring: State tracking and event callbacks
  • Error Handling: Comprehensive error propagation and filtering
  • Context Integration: Full support for Go's context.Context
  • Resource Management: Automatic cleanup and graceful shutdown
  • High Performance: Optimized for concurrent, high-throughput scenarios

Core Interfaces

## Server Interface

The Server interface provides methods for configuring, starting, and managing a socket server:

type Server interface {
    io.Closer
    RegisterFuncError(FuncError)
    RegisterFuncInfo(FuncInfo)
    RegisterFuncInfoServer(FuncInfoSrv)
    SetTLS(enable bool, config TLSConfig) error
    Listen(ctx context.Context) error
    Listener() (network NetworkProtocol, listener string, tls bool)
    Shutdown(ctx context.Context) error
    IsRunning() bool
    IsGone() bool
    OpenConnections() int64
}

Implementations: tcp.ServerTcp, udp.ServerUdp, unix.ServerUnix, unixgram.ServerUnixGram

## Client Interface

The Client interface provides methods for configuring and communicating with a socket server:

type Client interface {
    io.ReadWriteCloser
    SetTLS(enable bool, config TLSConfig, serverName string) error
    RegisterFuncError(FuncError)
    RegisterFuncInfo(FuncInfo)
    Connect(ctx context.Context) error
    IsConnected() bool
    Once(ctx context.Context, request io.Reader, fct Response) error
}

Implementations: tcp.ClientTCP, udp.ClientUDP, unix.ClientUnix, unixgram.ClientUnix

## Context Interface

The Context interface extends context.Context with I/O operations and connection state:

type Context interface {
    context.Context  // Deadline, Done, Err, Value
    io.Reader        // Read from connection
    io.Writer        // Write to connection
    io.Closer        // Close connection
    IsConnected() bool
    RemoteHost() string
    LocalHost() string
}

The Context is passed to HandlerFunc and provides all necessary operations for handling a connection.

Usage Examples

## TCP Server Example

import (
    "context"
    "log"
    "github.com/nabbar/golib/socket"
    "github.com/nabbar/golib/socket/config"
    "github.com/nabbar/golib/socket/server"
)

func main() {
    // Create configuration using builder
    cfg := config.NewServer().
        Network(config.NetworkTCP).
        Address(":8080").
        HandlerFunc(handleRequest).
        Build()

    // Create server from configuration
    srv, err := server.New(nil, cfg)
    if err != nil {
        log.Fatal(err)
    }
    defer srv.Close()

    // Start listening
    ctx := context.Background()
    if err := srv.Listen(ctx); err != nil {
        log.Fatal(err)
    }
}

func handleRequest(ctx socket.Context) {
    // Read request
    buf := make([]byte, 1024)
    n, err := ctx.Read(buf)
    if err != nil {
        return
    }

    // Process and respond
    response := []byte("Response: " + string(buf[:n]))
    ctx.Write(response)
}

## TCP Client Example

import (
    "context"
    "log"
    "github.com/nabbar/golib/socket/client"
    "github.com/nabbar/golib/socket/config"
)

func main() {
    // Create configuration
    cfg := config.NewClient().
        Network(config.NetworkTCP).
        Address("localhost:8080").
        Build()

    // Create client
    cli, err := client.New(cfg, nil)
    if err != nil {
        log.Fatal(err)
    }
    defer cli.Close()

    // Connect
    ctx := context.Background()
    if err := cli.Connect(ctx); err != nil {
        log.Fatal(err)
    }

    // Send request
    _, err = cli.Write([]byte("Hello, server!"))
    if err != nil {
        log.Fatal(err)
    }

    // Read response
    buf := make([]byte, 1024)
    n, err := cli.Read(buf)
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("Response: %s", buf[:n])
}

## Unix Socket Server Example (Linux/Darwin)

cfg := config.NewServer().
    Network(config.NetworkUnix).
    Address("/tmp/app.sock").
    HandlerFunc(handleRequest).
    Build()

srv, err := server.New(nil, cfg)
if err != nil {
    log.Fatal(err)
}
defer srv.Close()

ctx := context.Background()
if err := srv.Listen(ctx); err != nil {
    log.Fatal(err)
}

## UDP Server Example

cfg := config.NewServer().
    Network(config.NetworkUDP).
    Address(":9000").
    HandlerFunc(handleDatagram).
    Build()

srv, err := server.New(nil, cfg)
if err != nil {
    log.Fatal(err)
}
defer srv.Close()

ctx := context.Background()
if err := srv.Listen(ctx); err != nil {
    log.Fatal(err)
}

func handleDatagram(ctx socket.Context) {
    buf := make([]byte, 65536)
    n, err := ctx.Read(buf)
    if err != nil {
        return
    }
    log.Printf("Received datagram from %s: %s", ctx.RemoteHost(), buf[:n])
}

Protocol Selection Guide

## TCP (NetworkTCP, NetworkTCP4, NetworkTCP6)

Use TCP for:

  • Reliable, ordered data transmission
  • Network communication over internet/intranet
  • Long-lived connections
  • TLS/SSL encryption requirements
  • Applications requiring guaranteed delivery

Characteristics:

  • Connection-oriented
  • Stream-based (no message boundaries)
  • Automatic retransmission
  • Flow control and congestion control
  • Higher latency than UDP

## UDP (NetworkUDP, NetworkUDP4, NetworkUDP6)

Use UDP for:

  • Low-latency, connectionless communication
  • Real-time data (video, audio, gaming)
  • Broadcast/multicast scenarios
  • Metrics and monitoring data
  • Applications tolerating packet loss

Characteristics:

  • Connectionless (datagram-oriented)
  • Message boundaries preserved
  • No delivery guarantee
  • No ordering guarantee
  • Lower overhead than TCP

## Unix Domain Sockets (NetworkUnix)

Use Unix sockets for:

  • Inter-process communication on same host
  • Microservices on same machine
  • Database connections (PostgreSQL, MySQL)
  • Local daemon communication
  • Maximum performance with reliability

Characteristics:

  • Local only (same host)
  • Highest throughput, lowest latency
  • Connection-oriented (like TCP)
  • File-system based addressing
  • No network overhead

## Unix Datagram Sockets (NetworkUnixGram)

Use Unix datagram sockets for:

  • Local connectionless communication
  • System logging (syslog)
  • Event notifications
  • Metrics collection
  • Low-latency local messaging

Characteristics:

  • Local only (same host)
  • Connectionless (like UDP)
  • Message boundaries preserved
  • No network overhead
  • Higher performance than network UDP

Platform Support

┌──────────────┬───────┬───────┬─────────┬──────────┐
│  Protocol    │ Linux │ macOS │ Windows │ Other OS │
├──────────────┼───────┼───────┼─────────┼──────────┤
│  TCP         │   ✅   │   ✅   │    ✅    │    ✅     │
│  UDP         │   ✅   │   ✅   │    ✅    │    ✅     │
│  Unix        │   ✅   │   ✅   │    ❌    │    ❌     │
│  UnixGram    │   ✅   │   ✅   │    ❌    │    ❌     │
│  TLS (TCP)   │   ✅   │   ✅   │    ✅    │    ✅     │
└──────────────┴───────┴───────┴─────────┴──────────┘

Configuration

Configuration is managed through the config sub-package using builder patterns:

import "github.com/nabbar/golib/socket/config"

// Server configuration
srvCfg := config.NewServer().
    Network(config.NetworkTCP).
    Address(":8080").
    HandlerFunc(myHandler).
    BufferSize(32 * 1024).
    Delimiter('\n').
    Build()

// Client configuration
cliCfg := config.NewClient().
    Network(config.NetworkTCP).
    Address("localhost:8080").
    BufferSize(32 * 1024).
    Build()

See github.com/nabbar/golib/socket/config for complete configuration options.

Connection State Tracking

The package provides detailed connection state tracking through the ConnState type and FuncInfo callback:

type ConnState uint8
const (
    ConnectionDial       // Client dialing
    ConnectionNew        // New connection established
    ConnectionRead       // Reading data
    ConnectionCloseRead  // Closing read side
    ConnectionHandler    // Handler executing
    ConnectionWrite      // Writing data
    ConnectionCloseWrite // Closing write side
    ConnectionClose      // Closing connection
)

Register a callback to track state changes:

srv.RegisterFuncInfo(func(local, remote net.Addr, state socket.ConnState) {
    log.Printf("Connection %s -> %s: %s", remote, local, state)
})

Error Handling

The package provides comprehensive error handling through:

  1. Return Values: All operations return Go standard errors
  2. Error Callbacks: Register FuncError for async error notification
  3. Error Filtering: ErrorFilter() removes expected errors (closed connections)
  4. Context Integration: Errors propagate through context cancellation

Example error handling:

srv.RegisterFuncError(func(errs ...error) {
    for _, err := range errs {
        if err := socket.ErrorFilter(err); err != nil {
            log.Printf("Socket error: %v", err)
        }
    }
})

Thread Safety

All interfaces and implementations are designed for concurrent use:

  • Server: Listen() blocks, all other methods are thread-safe
  • Client: Connect() can be called concurrently, Read/Write should be serialized per connection
  • Context: All methods are safe for concurrent calls except Read/Write which follow io.Reader/Writer contracts

Thread-safe operations:

  • Server.IsRunning(), Server.OpenConnections()
  • Client.IsConnected()
  • Context.IsConnected(), Context.RemoteHost(), Context.LocalHost()
  • All callback registrations

Performance Characteristics

┌────────────────────┬────────────┬──────────┬──────────────┐
│  Operation         │ TCP/Unix   │   UDP    │  UnixGram    │
├────────────────────┼────────────┼──────────┼──────────────┤
│  Connection Setup  │  ~1-5 ms   │  ~0 ms   │   ~0 ms      │
│  Read Latency      │  ~100 µs   │  ~50 µs  │   ~10 µs     │
│  Write Latency     │  ~100 µs   │  ~50 µs  │   ~10 µs     │
│  Throughput        │  GB/s      │  GB/s    │   GB/s       │
│  Memory/Connection │  ~32 KB    │  ~16 KB  │   ~16 KB     │
└────────────────────┴────────────┴──────────┴──────────────┘

Performance tips:

  • Use appropriate buffer sizes (default: 32KB)
  • Enable TCP_NODELAY for low-latency applications
  • Use Unix sockets for local communication
  • Pool connections for high-throughput scenarios
  • Use UDP/UnixGram for low-latency datagrams

Best Practices

## 1. Resource Management

srv, err := server.New(nil, cfg)
if err != nil {
    return err
}
defer srv.Close()  // Always close resources

## 2. Context Usage

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
err := srv.Listen(ctx)

## 3. Error Handling

srv.RegisterFuncError(func(errs ...error) {
    for _, err := range errs {
        if err := socket.ErrorFilter(err); err != nil {
            log.Printf("Error: %v", err)
        }
    }
})

## 4. Graceful Shutdown

sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
<-sigCh

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
srv.Shutdown(ctx)

## 5. Connection Monitoring

srv.RegisterFuncInfo(func(local, remote net.Addr, state socket.ConnState) {
    log.Printf("%s: %s -> %s", state, remote, local)
})

Limitations

  1. Unix Sockets: Only available on Linux and Darwin (macOS)
  2. TLS Support: Only available for TCP-based protocols
  3. Multicast: Not directly supported (use raw sockets if needed)
  4. Protocol Mixing: Each socket handles only one protocol type
  5. Message Boundaries: TCP/Unix are stream-based (use delimiters or length prefixes)
  • github.com/nabbar/golib/socket/config: Configuration builders and validators
  • github.com/nabbar/golib/socket/client: Client factory and implementations
  • github.com/nabbar/golib/socket/server: Server factory and implementations
  • github.com/nabbar/golib/network/protocol: Protocol constants and utilities
  • github.com/nabbar/golib/certificates: TLS configuration and certificate management
  • github.com/nabbar/golib/ioutils/aggregator: Thread-safe write aggregation for socket logging
  • github.com/nabbar/golib/ioutils/delim: Delimiter-based reading for message framing

See Also

For detailed protocol-specific documentation:

  • TCP: github.com/nabbar/golib/socket/client/tcp, github.com/nabbar/golib/socket/server/tcp
  • UDP: github.com/nabbar/golib/socket/client/udp, github.com/nabbar/golib/socket/server/udp
  • Unix: github.com/nabbar/golib/socket/client/unix, github.com/nabbar/golib/socket/server/unix
  • UnixGram: github.com/nabbar/golib/socket/client/unixgram, github.com/nabbar/golib/socket/server/unixgram

For configuration:

  • github.com/nabbar/golib/socket/config

For examples:

  • See example_test.go in this package and sub-packages
Example (ConnectionLifecycle)

Example_connectionLifecycle demonstrates a complete connection lifecycle with proper state tracking and resource management.

package main

import (
	"fmt"
	"net"

	libsck "github.com/nabbar/golib/socket"
)

func main() {
	// Track connection state
	states := make([]libsck.ConnState, 0)

	// Info callback to track states
	trackState := func(local, remote net.Addr, state libsck.ConnState) {
		states = append(states, state)
	}

	// Simulate lifecycle
	localAddr := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 8080}
	remoteAddr := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 54321}

	// Client dialing
	trackState(localAddr, remoteAddr, libsck.ConnectionDial)

	// Connection established
	trackState(localAddr, remoteAddr, libsck.ConnectionNew)

	// Request processing
	trackState(localAddr, remoteAddr, libsck.ConnectionRead)
	trackState(localAddr, remoteAddr, libsck.ConnectionHandler)
	trackState(localAddr, remoteAddr, libsck.ConnectionWrite)

	// Connection teardown
	trackState(localAddr, remoteAddr, libsck.ConnectionCloseRead)
	trackState(localAddr, remoteAddr, libsck.ConnectionCloseWrite)
	trackState(localAddr, remoteAddr, libsck.ConnectionClose)

	// Display lifecycle
	fmt.Println("Connection lifecycle:")
	for i, state := range states {
		fmt.Printf("%d. %s\n", i+1, state.String())
	}

}
Output:

Connection lifecycle:
1. Dial Connection
2. New Connection
3. Read Incoming Stream
4. Run HandlerFunc
5. Write Outgoing Steam
6. Close Incoming Stream
7. Close Outgoing Stream
8. Close Connection
Example (ErrorHandling)

Example_errorHandling demonstrates comprehensive error handling patterns. This shows best practices for handling errors in socket operations.

package main

import (
	"fmt"
	"net"

	libsck "github.com/nabbar/golib/socket"
)

func main() {
	// Define comprehensive error handler
	handleErrors := func(operation string, errs ...error) {
		for _, err := range errs {
			// Filter expected errors
			if err := libsck.ErrorFilter(err); err != nil {
				// Log with context
				fmt.Printf("[%s] Error: %v\n", operation, err)

				// Handle specific error types
				if netErr, ok := err.(net.Error); ok {
					if netErr.Timeout() {
						fmt.Println("Network timeout")
					}
					if netErr.Temporary() {
						fmt.Println("Temporary error, can retry")
					}
				}
			}
		}
	}

	// Simulate various error scenarios
	handleErrors("connect", fmt.Errorf("connection refused"))
	handleErrors("read", fmt.Errorf("use of closed network connection")) // Filtered
	handleErrors("write", fmt.Errorf("broken pipe"))

}
Output:

[connect] Error: connection refused
[write] Error: broken pipe

Index

Examples

Constants

View Source
const DefaultBufferSize = 32 * 1024

DefaultBufferSize defines the default buffer size for socket I/O operations (32KB). This value is used for read/write operations when no custom buffer size is specified.

View Source
const EOL byte = '\n'

EOL defines the end-of-line delimiter (newline character) used as the default message delimiter for socket communication.

Variables

This section is empty.

Functions

func ErrorFilter added in v1.17.0

func ErrorFilter(err error) error

ErrorFilter filters out expected network errors that don't require handling. It returns nil for errors related to closed connections, which are normal during shutdown or connection cleanup. Other errors are returned unchanged.

This function is useful for error handling in connection management code where "use of closed network connection" errors are expected and can be safely ignored.

Example

ExampleErrorFilter demonstrates filtering expected network errors. This is useful during connection cleanup and shutdown sequences.

package main

import (
	"fmt"

	libsck "github.com/nabbar/golib/socket"
)

func main() {
	// Simulate various errors
	normalErr := fmt.Errorf("connection timeout")
	closedErr := fmt.Errorf("use of closed network connection")

	// Filter errors
	if err := libsck.ErrorFilter(normalErr); err != nil {
		fmt.Println("Error occurred:", err.Error())
	}

	// This error is filtered out (returns nil)
	if err := libsck.ErrorFilter(closedErr); err != nil {
		fmt.Println("Error occurred:", err.Error())
	} else {
		fmt.Println("Closed connection error filtered")
	}

	// Nil errors are handled safely
	if err := libsck.ErrorFilter(nil); err != nil {
		fmt.Println("Error occurred:", err.Error())
	} else {
		fmt.Println("No error")
	}

}
Output:

Error occurred: connection timeout
Closed connection error filtered
No error

Types

type Client added in v1.11.5

type Client interface {
	io.ReadWriteCloser

	// SetTLS enables or disables TLS encryption for the client connection.
	// This is only supported for TCP clients.
	//
	// Parameters:
	//   - enable: true to enable TLS, false to disable it
	//   - config: TLS configuration (see github.com/nabbar/golib/certificates)
	//   - serverName: the server name for TLS certificate verification
	//
	// Returns an error if TLS cannot be enabled or the configuration is invalid.
	SetTLS(enable bool, config libtls.TLSConfig, serverName string) error

	// RegisterFuncError registers a callback function to handle errors that occur
	// during client operations.
	RegisterFuncError(f FuncError)

	// RegisterFuncInfo registers a callback function to track connection state changes
	// during client operations.
	RegisterFuncInfo(f FuncInfo)

	// Connect establishes a connection to the server.
	// The context can be used to set a timeout or cancel the connection attempt.
	//
	// Returns an error if the connection cannot be established.
	Connect(ctx context.Context) error

	// IsConnected returns true if the client is currently connected to the server.
	IsConnected() bool

	// Once sends a single request to the server and processes the response.
	// This is a convenience method for one-shot request/response patterns.
	// The connection is automatically established if not already connected.
	//
	// Parameters:
	//   - ctx: context for cancellation and timeout control
	//   - request: reader containing the request data to send
	//   - fct: callback function to process the response
	//
	// Returns an error if the request cannot be sent or the response cannot be read.
	Once(ctx context.Context, request io.Reader, fct Response) error
}

Client defines the interface for socket client implementations. It provides methods for configuring, connecting to, and communicating with a socket server.

Client implementations are available for TCP, UDP, Unix domain sockets, and Unix datagram sockets in their respective subpackages.

See github.com/nabbar/golib/socket/client/tcp for TCP client implementation. See github.com/nabbar/golib/socket/client/udp for UDP client implementation. See github.com/nabbar/golib/socket/client/unix for Unix socket client implementation. See github.com/nabbar/golib/socket/client/unixgram for Unix datagram client implementation.

Example

ExampleClient demonstrates the Client interface usage pattern. This shows how clients are typically configured and used.

package main

import (
	"context"
	"fmt"
	"log"

	libsck "github.com/nabbar/golib/socket"
)

func main() {
	// This demonstrates the Client interface pattern
	// Actual client creation is done via protocol-specific packages

	var cli libsck.Client // Created via client.New() or protocol-specific constructors

	if cli != nil {
		// Register error handler
		cli.RegisterFuncError(func(errs ...error) {
			for _, err := range errs {
				log.Printf("Error: %v", err)
			}
		})

		// Connect to server
		ctx := context.Background()
		if err := cli.Connect(ctx); err != nil {
			log.Fatal(err)
		}
		defer cli.Close()

		// Write request
		if _, err := cli.Write([]byte("Hello, server!\n")); err != nil {
			log.Fatal(err)
		}

		// Read response
		buf := make([]byte, 1024)
		if n, err := cli.Read(buf); err == nil {
			fmt.Printf("Response: %s", buf[:n])
		}
	}

	fmt.Println("Client interface demonstrated")

}
Output:

Client interface demonstrated

type ConnState added in v1.11.5

type ConnState uint8

ConnState represents the current state of a network connection. It is used to track and report connection lifecycle events through the FuncInfo callback.

Example

ExampleConnState demonstrates the string representation of connection states. This is useful for logging and monitoring connection lifecycle events.

package main

import (
	"fmt"

	libsck "github.com/nabbar/golib/socket"
)

func main() {
	// Display all connection states
	states := []libsck.ConnState{
		libsck.ConnectionDial,
		libsck.ConnectionNew,
		libsck.ConnectionRead,
		libsck.ConnectionHandler,
		libsck.ConnectionWrite,
		libsck.ConnectionClose,
	}

	for _, state := range states {
		fmt.Println(state.String())
	}

}
Output:

Dial Connection
New Connection
Read Incoming Stream
Run HandlerFunc
Write Outgoing Steam
Close Connection
const (
	// ConnectionDial indicates the client is attempting to dial/connect to a server.
	ConnectionDial ConnState = iota
	// ConnectionNew indicates a new connection has been established.
	ConnectionNew
	// ConnectionRead indicates data is being read from the connection.
	ConnectionRead
	// ConnectionCloseRead indicates the read side of the connection is being closed.
	ConnectionCloseRead
	// ConnectionHandler indicates the request handler is being executed.
	ConnectionHandler
	// ConnectionWrite indicates data is being written to the connection.
	ConnectionWrite
	// ConnectionCloseWrite indicates the write side of the connection is being closed.
	ConnectionCloseWrite
	// ConnectionClose indicates the entire connection is being closed.
	ConnectionClose
)

func (ConnState) String added in v1.13.1

func (c ConnState) String() string

String returns a human-readable string representation of the connection state.

type Context added in v1.19.0

type Context interface {
	// context.Context provides deadline, cancellation signal propagation, and request-scoped values.
	// This allows handlers to respect timeouts and cancellation from the parent context.
	context.Context

	// io.Reader enables reading data from the connection.
	// Read blocks until data is available or an error occurs.
	//
	// For stream protocols (TCP, Unix): Reads bytes from the stream.
	// For datagram protocols (UDP, UnixGram): Reads one complete datagram.
	//
	// Returns:
	//   - n: Number of bytes read
	//   - err: io.EOF on connection close, or other I/O errors
	io.Reader

	// io.Writer enables writing data to the connection.
	// Write blocks until data is written or an error occurs.
	//
	// For stream protocols (TCP, Unix): Writes bytes to the stream.
	// For datagram protocols (UDP, UnixGram): Sends one complete datagram.
	//
	// Returns:
	//   - n: Number of bytes written
	//   - err: io.ErrClosedPipe if connection closed, or other I/O errors
	io.Writer

	// io.Closer enables closing the connection and releasing resources.
	// After Close is called, subsequent Read/Write operations will fail.
	//
	// Close is idempotent and safe to call multiple times.
	//
	// Returns:
	//   - err: Error if cleanup fails, nil otherwise
	io.Closer

	// IsConnected returns true if the connection is active and usable.
	// Returns false after Close() is called or if the connection is broken.
	//
	// This method is safe for concurrent calls and uses atomic operations.
	//
	// Example:
	//
	//	if ctx.IsConnected() {
	//	    ctx.Write(data)
	//	}
	IsConnected() bool

	// RemoteHost returns the remote endpoint address as a string.
	// The format depends on the protocol:
	//   - TCP/UDP: "host:port" (e.g., "192.168.1.10:54321")
	//   - Unix: "socket-path" (e.g., "/tmp/app.sock")
	//
	// The returned string includes the protocol code for disambiguation.
	//
	// This method is safe for concurrent calls as it returns an immutable value
	// set during connection initialization.
	//
	// Example:
	//
	//	remote := ctx.RemoteHost()
	//	log.Printf("Connection from: %s", remote)
	RemoteHost() string

	// LocalHost returns the local endpoint address as a string.
	// The format depends on the protocol:
	//   - TCP/UDP: "host:port" (e.g., "0.0.0.0:8080")
	//   - Unix: "socket-path" (e.g., "/tmp/app.sock")
	//
	// The returned string includes the protocol code for disambiguation.
	//
	// This method is safe for concurrent calls as it returns an immutable value
	// set during connection initialization.
	//
	// Example:
	//
	//	local := ctx.LocalHost()
	//	log.Printf("Server listening on: %s", local)
	LocalHost() string
}

Context extends context.Context with I/O operations and connection state for socket communication. It combines the standard context interface with Reader, Writer, and Closer interfaces, plus connection-specific methods for state checking and address retrieval.

The Context interface is passed to HandlerFunc in server implementations and provides all necessary operations for handling a connection within a single abstraction. This design allows handlers to access the underlying connection context, perform I/O operations, and query connection state without needing multiple parameters.

Usage

Server-side handler example:

func handleConnection(ctx socket.Context) {
    // Check connection state
    if !ctx.IsConnected() {
        return
    }

    // Log connection information
    log.Printf("Handling connection from %s to %s", ctx.RemoteHost(), ctx.LocalHost())

    // Read from connection
    buf := make([]byte, 1024)
    n, err := ctx.Read(buf)
    if err != nil {
        return
    }

    // Write response
    response := []byte("Response: " + string(buf[:n]))
    ctx.Write(response)

    // Check context cancellation
    select {
    case <-ctx.Done():
        log.Println("Context canceled")
        return
    default:
    }
}

Interface Composition

The Context interface embeds multiple standard interfaces:

  • context.Context: Provides deadline, cancellation, and value propagation
  • io.Reader: Enables reading data from the connection
  • io.Writer: Enables writing data to the connection
  • io.Closer: Provides resource cleanup

Plus custom methods for connection-specific operations:

  • IsConnected(): Check if connection is still active
  • RemoteHost(): Get remote endpoint address
  • LocalHost(): Get local endpoint address

Thread Safety

Thread safety depends on the specific implementation:

  • Read/Write: Follow io.Reader/Writer contracts (not safe for concurrent calls on same connection)
  • IsConnected: Safe for concurrent calls (uses atomic operations)
  • RemoteHost/LocalHost: Safe for concurrent calls (immutable after creation)
  • context.Context methods: Safe for concurrent calls (immutable)

Connection Lifecycle

New Connection → IsConnected() = true
                      ↓
             Read/Write Operations
                      ↓
                  Close()
                      ↓
              IsConnected() = false

Implementation Notes

Implementations are provided in protocol-specific sub-packages:

  • TCP: github.com/nabbar/golib/socket/server/tcp.sCtx
  • UDP: github.com/nabbar/golib/socket/server/udp.sCtx
  • Unix: github.com/nabbar/golib/socket/server/unix.sCtx
  • UnixGram: github.com/nabbar/golib/socket/server/unixgram.sCtx

Each implementation adapts the base connection type (net.Conn, net.PacketConn) to this unified interface while preserving protocol-specific characteristics.

Example

ExampleContext demonstrates using the Context interface in a handler. This shows how to access connection state and perform I/O operations.

package main

import (
	"fmt"

	libsck "github.com/nabbar/golib/socket"
)

func main() {
	// This example demonstrates Context usage patterns
	// In real usage, Context is provided by the server to HandlerFunc

	// Example handler showing Context usage
	handler := func(ctx libsck.Context) {
		// Check connection state
		if !ctx.IsConnected() {
			fmt.Println("Connection closed")
			return
		}

		// Get connection information
		fmt.Printf("Local: %s, Remote: %s\n", ctx.LocalHost(), ctx.RemoteHost())

		// Check for cancellation
		select {
		case <-ctx.Done():
			fmt.Println("Context canceled:", ctx.Err())
			return
		default:
		}

		// Perform I/O operations
		buf := make([]byte, 1024)
		if n, err := ctx.Read(buf); err == nil {
			fmt.Printf("Read %d bytes\n", n)
			ctx.Write([]byte("ACK"))
		}
	}

	_ = handler
	fmt.Println("Context usage demonstrated")

}
Output:

Context usage demonstrated

type FuncError

type FuncError func(e ...error)

FuncError is a callback function type for handling errors that occur during socket operations. It receives one or more errors as parameters.

Example

ExampleFuncError demonstrates registering an error callback for socket operations. This pattern is used in both client and server implementations.

package main

import (
	"fmt"
	"log"

	libsck "github.com/nabbar/golib/socket"
)

func main() {
	// Define error handler
	errHandler := func(errs ...error) {
		for _, err := range errs {
			// Filter expected errors
			if err := libsck.ErrorFilter(err); err != nil {
				log.Printf("Socket error: %v", err)
			}
		}
	}

	// Simulate error handling
	errHandler(fmt.Errorf("connection refused"))
	errHandler(fmt.Errorf("use of closed network connection")) // Filtered
	errHandler(fmt.Errorf("timeout"), fmt.Errorf("network unreachable"))

	fmt.Println("Error handler demonstrated")

}
Output:

Error handler demonstrated

type FuncInfo added in v1.11.5

type FuncInfo func(local, remote net.Addr, state ConnState)

FuncInfo is a callback function type for tracking connection state changes. It receives the local address, remote address, and the current connection state. This is useful for logging, monitoring, and debugging connection lifecycles.

Example

ExampleFuncInfo demonstrates tracking connection state changes. This is useful for monitoring, logging, and debugging.

package main

import (
	"fmt"
	"net"

	libsck "github.com/nabbar/golib/socket"
)

func main() {
	// Define connection info handler
	infoHandler := func(local, remote net.Addr, state libsck.ConnState) {
		fmt.Printf("[%s] %s -> %s\n", state.String(), remote.String(), local.String())
	}

	// Simulate connection lifecycle
	localAddr := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 8080}
	remoteAddr := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 54321}

	infoHandler(localAddr, remoteAddr, libsck.ConnectionNew)
	infoHandler(localAddr, remoteAddr, libsck.ConnectionRead)
	infoHandler(localAddr, remoteAddr, libsck.ConnectionWrite)
	infoHandler(localAddr, remoteAddr, libsck.ConnectionClose)

}
Output:

[New Connection] 127.0.0.1:54321 -> 127.0.0.1:8080
[Read Incoming Stream] 127.0.0.1:54321 -> 127.0.0.1:8080
[Write Outgoing Steam] 127.0.0.1:54321 -> 127.0.0.1:8080
[Close Connection] 127.0.0.1:54321 -> 127.0.0.1:8080

type FuncInfoSrv added in v1.13.1

type FuncInfoSrv func(msg string)

FuncInfoSrv is a callback function type for receiving informational messages about the server's listening state and lifecycle events.

type Handler

type Handler interface {
	// HandlerSck processes an incoming connection using the provided Context.
	// This method is called for each new connection and should handle the complete
	// request/response cycle before returning.
	//
	// The Context parameter provides access to:
	//   - Connection I/O (Read/Write)
	//   - Connection state (IsConnected)
	//   - Endpoint addresses (RemoteHost/LocalHost)
	//   - Cancellation signaling (Done, Err)
	//
	// Implementations should:
	//   - Check ctx.IsConnected() before I/O operations
	//   - Handle ctx.Done() for graceful cancellation
	//   - Return when processing is complete or on error
	//   - Not call ctx.Close() (managed by server)
	HandlerSck(ctx Context)
}

Handler is an interface for types that can handle socket connections. It provides an alternative to HandlerFunc for object-oriented handler implementations.

Types implementing this interface can be used in server configurations where a method receiver is preferred over a function pointer, enabling stateful handlers and easier testing through interface mocking.

Example:

type MyHandler struct {
    db *sql.DB
}

func (h *MyHandler) HandlerSck(ctx socket.Context) {
    // Handle connection with access to h.db
    buf := make([]byte, 1024)
    n, _ := ctx.Read(buf)
    // Process with database...
}
Example

ExampleHandler demonstrates using a stateful handler type instead of HandlerFunc. This is useful for handlers that need to maintain state or access dependencies.

package main

import (
	"fmt"

	libsck "github.com/nabbar/golib/socket"
)

func main() {
	// Define a stateful handler type
	type EchoHandler struct {
		prefix string
	}

	// Implement the Handler interface
	handleFunc := func(h *EchoHandler, ctx libsck.Context) {
		buf := make([]byte, 1024)
		n, err := ctx.Read(buf)
		if err != nil {
			return
		}

		// Use handler state
		response := []byte(h.prefix + string(buf[:n]))
		ctx.Write(response)
	}

	// Create handler instance
	handler := &EchoHandler{prefix: "Echo: "}

	// Use in server (would be: cfg.Handler = handler)
	_ = handleFunc
	_ = handler

	fmt.Println("Stateful handler demonstrated")

}
Output:

Stateful handler demonstrated

type HandlerFunc added in v1.19.0

type HandlerFunc func(ctx Context)

HandlerFunc is a server-side callback function type for processing incoming requests. It receives a Reader for reading the request and a Writer for sending the response. The handler is responsible for reading the complete request and writing the complete response.

Example

ExampleHandlerFunc demonstrates a basic request handler for socket servers. This shows the typical pattern for handling connections.

package main

import (
	"fmt"
	"io"

	libsck "github.com/nabbar/golib/socket"
)

func main() {
	// Define handler function
	handler := func(ctx libsck.Context) {
		// Check if connection is active
		if !ctx.IsConnected() {
			return
		}

		// Log connection info
		fmt.Printf("Handling connection from %s\n", ctx.RemoteHost())

		// Read request
		buf := make([]byte, 1024)
		n, err := ctx.Read(buf)
		if err != nil {
			if err != io.EOF {
				fmt.Printf("Read error: %v\n", err)
			}
			return
		}

		// Process request
		request := string(buf[:n])
		fmt.Printf("Received: %s\n", request)

		// Send response
		response := []byte("Response: " + request)
		if _, err := ctx.Write(response); err != nil {
			fmt.Printf("Write error: %v\n", err)
			return
		}

		fmt.Println("Request handled successfully")
	}

	// Handler is now ready to be used in server configuration
	_ = handler
	fmt.Println("Handler function created")

}
Output:

Handler function created

type Response added in v1.12.2

type Response func(r io.Reader)

Response is a client-side callback function type for processing responses received from the server. It receives an io.Reader to read the response data.

Example

ExampleResponse demonstrates processing server responses on the client side. This callback is used with Client.Once() for request/response patterns.

package main

import (
	"fmt"
	"io"
	"log"
)

func main() {
	// Define response handler
	responseHandler := func(r io.Reader) {
		buf := make([]byte, 1024)
		n, err := r.Read(buf)
		if err != nil && err != io.EOF {
			log.Printf("Response error: %v", err)
			return
		}

		response := string(buf[:n])
		fmt.Printf("Server response: %s\n", response)

		// Process response data
		// Parse, validate, etc.
	}

	_ = responseHandler
	fmt.Println("Response handler demonstrated")

}
Output:

Response handler demonstrated

type Server

type Server interface {
	io.Closer

	// RegisterFuncError registers a callback function to handle errors that occur
	// during server operation. Multiple error handlers can be registered.
	RegisterFuncError(f FuncError)

	// RegisterFuncInfo registers a callback function to track connection state changes.
	// This is useful for monitoring, logging, and debugging connection lifecycles.
	RegisterFuncInfo(f FuncInfo)

	// RegisterFuncInfoServer registers a callback function to receive informational
	// messages about the server's state and operations.
	RegisterFuncInfoServer(f FuncInfoSrv)

	// SetTLS enables or disables TLS encryption for the server.
	// This is only supported for TCP servers. For other socket types, this method
	// may return an error or be a no-op.
	//
	// Parameters:
	//   - enable: true to enable TLS, false to disable it
	//   - config: TLS configuration (see github.com/nabbar/golib/certificates)
	//
	// Returns an error if TLS cannot be enabled or the configuration is invalid.
	SetTLS(enable bool, config libtls.TLSConfig) error

	// Listen starts the server and begins accepting incoming connections.
	// This method blocks until the context is canceled or an error occurs.
	// The context can be used to control the server's lifetime.
	//
	// Returns an error if the server cannot start or encounters a fatal error.
	Listen(ctx context.Context) error

	// Listener returns information about the server's current listening configuration.
	//
	// Returns:
	//   - network: The protocol type (TCP, UDP, Unix, UnixGram)
	//   - listener: The address string the server is listening on
	//   - tls: True if TLS encryption is enabled (TCP only)
	//
	// Example:
	//
	//	network, addr, tls := server.Listener()
	//	log.Printf("Server listening on %s %s (TLS: %v)", network.Code(), addr, tls)
	Listener() (network libptc.NetworkProtocol, listener string, tls bool)

	// Shutdown gracefully stops the server and closes all open connections.
	// The context controls how long to wait for connections to close cleanly.
	//
	// Returns an error if the shutdown process fails.
	Shutdown(ctx context.Context) error

	// IsRunning returns true if the server is currently running and accepting connections.
	IsRunning() bool

	// IsGone returns true if the server has completed its shutdown process.
	// Once IsGone returns true, the server cannot be restarted.
	IsGone() bool

	// OpenConnections returns the current number of active connections being handled
	// by the server. This is useful for monitoring and graceful shutdown.
	OpenConnections() int64
}

Server defines the interface for socket server implementations. It provides methods for configuring, starting, and managing a socket server that can handle multiple concurrent connections.

Server implementations are available for TCP, UDP, Unix domain sockets, and Unix datagram sockets in their respective subpackages.

See github.com/nabbar/golib/socket/server/tcp for TCP server implementation. See github.com/nabbar/golib/socket/server/udp for UDP server implementation. See github.com/nabbar/golib/socket/server/unix for Unix socket server implementation. See github.com/nabbar/golib/socket/server/unixgram for Unix datagram server implementation.

Example

ExampleServer demonstrates the Server interface usage pattern. This shows how servers are typically configured and started.

package main

import (
	"context"
	"fmt"
	"log"
	"net"
	"time"

	libsck "github.com/nabbar/golib/socket"
)

func main() {
	// This demonstrates the Server interface pattern
	// Actual server creation is done via protocol-specific packages

	var srv libsck.Server // Created via server.New() or protocol-specific constructors

	if srv != nil {
		// Register error handler
		srv.RegisterFuncError(func(errs ...error) {
			for _, err := range errs {
				log.Printf("Error: %v", err)
			}
		})

		// Register connection state tracker
		srv.RegisterFuncInfo(func(local, remote net.Addr, state libsck.ConnState) {
			log.Printf("[%s] %s -> %s", state, remote, local)
		})

		// Start server with timeout
		ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
		defer cancel()

		// This would block until context is canceled or error occurs
		_ = srv.Listen(ctx)

		// Graceful shutdown
		shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 10*time.Second)
		defer shutdownCancel()
		srv.Shutdown(shutdownCtx)
	}

	fmt.Println("Server interface demonstrated")

}
Output:

Server interface demonstrated

type UpdateConn added in v1.17.0

type UpdateConn func(co net.Conn)

UpdateConn is a callback function type for modifying a net.Conn before it is used. This allows for custom connection configuration such as setting timeouts, buffer sizes, or other socket options.

Example

ExampleUpdateConn demonstrates customizing connection settings. This callback is used to configure socket options before use.

package main

import (
	"fmt"
	"net"
	"time"
)

func main() {
	// Define connection customization function
	updateConn := func(conn net.Conn) {
		// Set connection deadlines
		if tcpConn, ok := conn.(*net.TCPConn); ok {
			// Disable Nagle's algorithm for low latency
			_ = tcpConn.SetNoDelay(true)

			// Set keepalive
			_ = tcpConn.SetKeepAlive(true)
			_ = tcpConn.SetKeepAlivePeriod(30 * time.Second)

			// Set buffer sizes
			_ = tcpConn.SetReadBuffer(64 * 1024)
			_ = tcpConn.SetWriteBuffer(64 * 1024)
		}

		// Set overall deadlines
		_ = conn.SetDeadline(time.Now().Add(5 * time.Minute))
	}

	_ = updateConn
	fmt.Println("Connection customization demonstrated")

}
Output:

Connection customization demonstrated

Directories

Path Synopsis
Package client provides a unified, platform-aware factory for creating socket clients across different network protocols.
Package client provides a unified, platform-aware factory for creating socket clients across different network protocols.
tcp
Package tcp provides a robust, production-ready TCP client implementation with support for TLS, connection management, and comprehensive monitoring capabilities.
Package tcp provides a robust, production-ready TCP client implementation with support for TLS, connection management, and comprehensive monitoring capabilities.
udp
Package udp provides a UDP client implementation with callback mechanisms for datagram communication.
Package udp provides a UDP client implementation with callback mechanisms for datagram communication.
unix
Package unix provides a high-performance UNIX domain socket client implementation for local inter-process communication.
Package unix provides a high-performance UNIX domain socket client implementation for local inter-process communication.
unixgram
Package unixgram provides a Unix domain datagram socket client implementation.
Package unixgram provides a Unix domain datagram socket client implementation.
Package config provides configuration structures for creating socket clients and servers.
Package config provides configuration structures for creating socket clients and servers.
Package server provides a unified, platform-aware factory for creating socket servers across different network protocols.
Package server provides a unified, platform-aware factory for creating socket servers across different network protocols.
tcp
Package tcp provides a robust, production-ready TCP server implementation with support for TLS, connection management, and comprehensive monitoring capabilities.
Package tcp provides a robust, production-ready TCP server implementation with support for TLS, connection management, and comprehensive monitoring capabilities.
udp
Package udp provides a UDP server implementation with connectionless datagram support.
Package udp provides a UDP server implementation with connectionless datagram support.
unix
Package unix provides a robust, production-ready Unix domain socket server implementation for Go applications.
Package unix provides a robust, production-ready Unix domain socket server implementation for Go applications.
unixgram
Package unixgram provides a Unix domain datagram socket server implementation.
Package unixgram provides a Unix domain datagram socket server implementation.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL