server

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: 8 Imported by: 0

README

Socket Server Factory

Go Version License Coverage

Platform-aware socket server factory providing unified creation API for TCP, UDP, and Unix domain socket servers with automatic protocol delegation.


Table of Contents


Overview

The server package provides a unified factory for creating socket servers across different network protocols. It automatically selects and instantiates the appropriate protocol-specific implementation based on configuration, providing a consistent API through the socket.Server interface.

Design Philosophy
  1. Single Entry Point: One New() function for all protocol types
  2. Platform Awareness: Automatic protocol availability based on OS
  3. Zero Overhead: Direct delegation without wrapping layers
  4. Type Safety: Configuration-based creation with validation
  5. Consistent API: All servers implement the same interface
Key Features
  • Unified Factory: Single entry point for TCP, UDP, Unix socket creation
  • Platform-Aware: Automatic Unix socket support detection (Linux/Darwin)
  • Protocol Validation: Returns error for unsupported protocols
  • Zero Dependencies: Only delegates to protocol-specific packages
  • Minimal Overhead: Single switch statement, no wrapping
  • Thread-Safe: All created servers safe for concurrent use

Architecture

Factory Pattern

The server package implements the Factory Method design pattern:

           ┌─────────────────────────┐
           │   server.New(cfg)       │
           │   (Factory Function)    │
           └───────────┬─────────────┘
                       │
          ┌────────────┼────────────┬────────────┐
          │            │            │            │
          ▼            ▼            ▼            ▼
    ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐
    │   TCP   │  │   UDP   │  │  Unix   │  │UnixGram │
    │ Server  │  │ Server  │  │ Server  │  │ Server  │
    └────┬────┘  └────┬────┘  └────┬────┘  └────┬────┘
         │            │            │            │
         └────────────┴────────────┴────────────┘
                      │
            ┌─────────▼─────────┐
            │  socket.Server    │
            │   (Interface)     │
            └───────────────────┘

Benefits:

  • Simplified server creation
  • Consistent error handling
  • Protocol abstraction
  • Easy protocol switching
Platform-Specific Implementations

Build constraints determine protocol availability:

┌─────────────────────┬──────────────────┬─────────────────────┐
│  File               │  Build Tag       │  Protocols          │
├─────────────────────┼──────────────────┼─────────────────────┤
│  interface_linux.go │  linux           │  TCP, UDP, Unix, *  │
│  interface_darwin.go│  darwin          │  TCP, UDP, Unix, *  │
│  interface_other.go │  !linux&&!darwin │  TCP, UDP only      │
└─────────────────────┴──────────────────┴─────────────────────┘

* Unix includes Unix and UnixGram protocols

Why Platform-Specific?

  • Unix domain sockets not available on Windows
  • Compilation errors prevented on unsupported platforms
  • Clear error messages for unsupported protocols
Delegation Flow
1. User calls server.New(upd, handler, cfg)
   │
2. Factory validates cfg.Network
   │
3. Switch on protocol type
   │
   ├─ NetworkTCP* → tcp.New(upd, handler, cfg)
   ├─ NetworkUDP* → udp.New(upd, handler, cfg)
   ├─ NetworkUnix → unix.New(upd, handler, cfg)
   ├─ NetworkUnixGram → unixgram.New(upd, handler, cfg)
   └─ Other → ErrInvalidProtocol
   │
4. Return socket.Server implementation

Delegation Properties:

  • Zero-copy: No wrapping, direct return
  • Atomic: Single function call
  • Type-safe: Compile-time protocol validation

Performance

Factory Overhead

Based on comprehensive benchmarks (100 samples):

Operation Median Mean Max
TCP Creation <1ms <1ms <10ms
UDP Creation <1ms <1ms <10ms
Unix Creation <1ms <1ms <10ms
Concurrent Creation (10) 200µs 200µs 400µs

Overhead Analysis:

  • Factory adds ~1µs (single switch statement)
  • Total time dominated by protocol-specific initialization
  • No measurable performance difference vs. direct package use
Protocol Comparison
Protocol Throughput Latency Best For
TCP High Low Network IPC, reliability
UDP Very High Very Low Datagrams, speed
Unix Highest Lowest Local IPC, performance
UnixGram Highest Lowest Local datagrams

Subpackages

tcp

Purpose: TCP server implementation with TLS support.

Key Features:

  • Connection-oriented, reliable
  • TLS/SSL encryption support
  • Graceful shutdown
  • Idle timeout management
  • Thread-safe connection handling

Performance: ~500K req/sec (localhost echo)

Documentation: tcp/README.md


udp

Purpose: UDP server implementation for datagram protocols.

Key Features:

  • Connectionless, fast
  • Datagram handling
  • Broadcast/multicast support
  • Low-latency operations

Performance: Very high throughput for small packets

Documentation: udp/README.md


unix

Purpose: Unix domain socket server (connection-oriented).

Key Features:

  • Local IPC only (same host)
  • File system permissions
  • Higher throughput than TCP loopback
  • Lower latency than TCP

Performance: ~1M req/sec (localhost echo)

Platforms: Linux, Darwin/macOS only

Documentation: unix/README.md


unixgram

Purpose: Unix domain datagram socket server.

Key Features:

  • Connectionless local IPC
  • Fast datagram delivery
  • File system permissions
  • Low overhead

Performance: Very high throughput for local communication

Platforms: Linux, Darwin/macOS only

Documentation: unixgram/README.md


Use Cases

1. Cross-Platform Network Service

Problem: Build a service that works on all platforms.

Solution: Use TCP (available everywhere).

cfg := config.Server{
    Network: protocol.NetworkTCP,
    Address: ":8080",
}

srv, err := server.New(nil, handler, cfg)
2. High-Performance Local IPC

Problem: Fast communication between processes on same host.

Solution: Use Unix sockets (when available).

cfg := config.Server{
    Network:   protocol.NetworkUnix,
    Address:   "/tmp/app.sock",
    PermFile:  perm.Perm(0660),
    GroupPerm: -1,
}

srv, err := server.New(nil, handler, cfg)
if err == config.ErrInvalidProtocol {
    // Fall back to TCP on unsupported platforms
    cfg.Network = protocol.NetworkTCP
    cfg.Address = ":8080"
    srv, err = server.New(nil, handler, cfg)
}
3. Real-Time Metrics Collection

Problem: Collect metrics with minimal overhead.

Solution: Use UDP for fast, fire-and-forget delivery.

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

srv, err := server.New(nil, handler, cfg)
4. Secure Web Service

Problem: HTTPS server with TLS.

Solution: Use TCP with TLS configuration.

cfg := config.Server{
    Network: protocol.NetworkTCP,
    Address: ":443",
    TLS: config.TLS{
        Enable: true,
        Config: tlsConfig,
    },
}

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

Quick Start

Installation
go get github.com/nabbar/golib/socket/server
Basic Examples

TCP Server:

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

func main() {
    handler := func(c socket.Context) {
        defer c.Close()
        // Handle connection
    }

    cfg := config.Server{
        Network: protocol.NetworkTCP,
        Address: ":8080",
    }

    srv, err := server.New(nil, handler, cfg)
    if err != nil {
        panic(err)
    }

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

UDP Server:

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

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

Unix Socket Server (with fallback):

import "github.com/nabbar/golib/file/perm"

cfg := config.Server{
    Network:   protocol.NetworkUnix,
    Address:   "/tmp/app.sock",
    PermFile:  perm.Perm(0660),
    GroupPerm: -1,
}

srv, err := server.New(nil, handler, cfg)
if err == config.ErrInvalidProtocol {
    // Platform doesn't support Unix sockets
    cfg.Network = protocol.NetworkTCP
    cfg.Address = ":8080"
    srv, err = server.New(nil, handler, cfg)
}

With Connection Configuration:

import "net"

upd := func(c net.Conn) {
    if tcpConn, ok := c.(*net.TCPConn); ok {
        tcpConn.SetKeepAlive(true)
        tcpConn.SetKeepAlivePeriod(30 * time.Second)
    }
}

srv, err := server.New(upd, handler, cfg)

Best Practices

✅ DO

Choose Protocol for Use Case:

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

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

// Metrics/logging → UDP (fast)
cfg.Network = protocol.NetworkUDP

Handle Platform Limitations:

srv, err := server.New(nil, handler, cfg)
if err == config.ErrInvalidProtocol {
    // Implement fallback strategy
}

Resource Cleanup:

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

Graceful Shutdown:

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

if err := srv.Shutdown(ctx); err != nil {
    log.Printf("Shutdown error: %v", err)
}
❌ DON'T

Don't Ignore Errors:

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

// ✅ GOOD
srv, err := server.New(nil, handler, cfg)
if err != nil {
    return fmt.Errorf("server creation failed: %w", err)
}

Don't Assume Unix Support:

// ❌ BAD: Will fail on Windows
srv, _ := server.New(nil, handler, config.Server{
    Network: protocol.NetworkUnix,
    Address: "/tmp/app.sock",
})

// ✅ GOOD: Check and fallback
if err == config.ErrInvalidProtocol {
    // Use TCP as fallback
}

Don't Mix Protocol-Specific Options:

// ❌ BAD: TLS on Unix socket (ignored)
cfg := config.Server{
    Network: protocol.NetworkUnix,
    TLS: config.TLS{Enable: true}, // Has no effect
}

// ✅ GOOD: TLS only for TCP
if cfg.Network.IsTCP() {
    cfg.TLS.Enable = true
}

API Reference

Factory Function
func New(upd socket.UpdateConn, handler socket.HandlerFunc, cfg config.Server) (socket.Server, error)

Parameters:

  • upd: Optional connection configuration callback (can be nil)
  • handler: Required connection/datagram handler function
  • cfg: Server configuration including protocol and address

Returns:

  • socket.Server: Server instance implementing standard interface
  • error: config.ErrInvalidProtocol if protocol unsupported

Example:

srv, err := server.New(nil, handler, config.Server{
    Network: protocol.NetworkTCP,
    Address: ":8080",
})
Configuration
type config.Server struct {
    Network        protocol.Protocol // Required: NetworkTCP, NetworkUDP, etc.
    Address        string            // Required: ":port" or "/path/to/socket"
    PermFile       perm.Perm         // Unix only: file permissions
    GroupPerm      int               // Unix only: group ID
    ConIdleTimeout time.Duration     // Optional: idle timeout
    TLS            config.TLS        // TCP only: TLS configuration
}

Protocol Values:

  • protocol.NetworkTCP, NetworkTCP4, NetworkTCP6
  • protocol.NetworkUDP, NetworkUDP4, NetworkUDP6
  • protocol.NetworkUnix (Linux/Darwin only)
  • protocol.NetworkUnixGram (Linux/Darwin only)
Error Codes
config.ErrInvalidProtocol  // Protocol not supported or invalid

Handling:

if err == config.ErrInvalidProtocol {
    // Implement fallback or return user-friendly error
}

Contributing

Contributions are welcome! Please follow these guidelines:

  1. Code Quality

    • Follow Go best practices and idioms
    • Maintain 100% code coverage
    • Pass all tests including race detector
    • Use gofmt and golint
  2. AI Usage Policy

    • Do NOT use AI for implementing package functionality
    • AI may assist with tests, documentation, debugging
    • All AI-assisted contributions must be reviewed by humans
  3. Testing

    • Add tests for new features
    • Use Ginkgo v2 / Gomega
    • Ensure zero race conditions
    • Maintain coverage at 100%
  4. Documentation

    • Update GoDoc comments
    • Add examples for new features
    • Update README.md and TESTING.md
    • Follow existing documentation structure
  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

Improvements & Security

Current Status

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

Code Quality Metrics
  • 100.0% test coverage
  • Zero race conditions detected
  • Thread-safe operations
  • Minimal overhead (<1µs factory cost)
  • Platform-aware compilation
  • 41 comprehensive test specs
Future Enhancements (Non-urgent)

Features:

  1. Protocol auto-detection from address format
  2. Configuration presets for common scenarios
  3. Server pool management (multiple servers)
  4. Health check endpoints integration

Performance:

  1. Compile-time protocol selection (build tags)
  2. Protocol-specific fast paths
  3. Configuration validation caching

Monitoring:

  1. Factory metrics (creation rate, errors)
  2. Protocol usage statistics
  3. OpenTelemetry integration

These are optional improvements and not required for production use. The current implementation is stable and feature-complete.

Suggestions and contributions are welcome via GitHub issues.


Resources

Internal Documentation
  • GoDoc - Complete API documentation
  • TESTING.md - Test suite documentation
  • doc.go - Detailed package documentation
Subpackage Documentation
External References

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/server
Version: See releases for versioning

Documentation

Overview

Package server provides a unified, platform-aware factory for creating socket servers across different network protocols. It serves as a convenient entry point that automatically selects the appropriate protocol-specific implementation based on the network type specified in the configuration.

Overview

This package acts as a factory that abstracts protocol-specific server implementations and provides a consistent API through the github.com/nabbar/golib/socket.Server interface. The factory automatically delegates to the appropriate sub-package based on the protocol:

  • TCP, TCP4, TCP6: github.com/nabbar/golib/socket/server/tcp
  • UDP, UDP4, UDP6: github.com/nabbar/golib/socket/server/udp
  • Unix (Linux/Darwin): github.com/nabbar/golib/socket/server/unix
  • UnixGram (Linux/Darwin): github.com/nabbar/golib/socket/server/unixgram

Architecture

## Factory Pattern

The server package implements the Factory Method pattern, providing a single entry point (New) that instantiates the appropriate server implementation:

┌─────────────────────────────────────────────────────┐
│                     server.New()                    │
│                   (Factory Function)                │
└───────────────────────────┬─────────────────────────┘
                            │
        ┌─────────────┬─────┴───────┬───────────┐
        │             │             │           │
        ▼             ▼             ▼           ▼
 ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐
 │   TCP    │  │   UDP    │  │   Unix   │  │ UnixGram │
 │  Server  │  │  Server  │  │  Server  │  │  Server  │
 └──────────┘  └──────────┘  └──────────┘  └──────────┘
      │             │             │             │
      └─────────────┴──────┬──────┴─────────────┘
                           │
                 ┌─────────▼─────────┐
                 │  socket.Server    │
                 │    (Interface)    │
                 └───────────────────┘

## Platform-Specific Implementations

The package uses build constraints to provide platform-specific implementations:

  • interface_linux.go (//go:build linux): Full protocol support including Unix sockets
  • interface_darwin.go (//go:build darwin): Full protocol support including Unix sockets
  • interface_other.go (//go:build !linux && !darwin): TCP and UDP only

This ensures that Unix domain sockets are only available on platforms that support them.

## Component Diagram

┌───────────────────────────────────────────────────────────┐
│                    server Package                         │
├───────────────────────────────────────────────────────────┤
│                                                           │
│  ┌─────────────────────────────────────────────────┐      │
│  │          New(upd, handler, cfg)                 │      │
│  │                                                 │      │
│  │  1. Validate config.Network                     │      │
│  │  2. Switch on protocol type                     │      │
│  │  3. Delegate to appropriate package             │      │
│  │  4. Return socket.Server implementation         │      │
│  └─────────────────────────┬───────────────────────┘      │
│                            │                              │
│                            ▼                              │
│     ┌───────────────┬──────┴────┬──────────────┐          │
│     │               │           │              │          │
│     ▼               ▼           ▼              ▼          │
│  tcp.New()       udp.New()  unix.New() unixgram.New()     │
│                                                           │
└───────────────────────────────────────────────────────────┘

Design Philosophy

  1. Simplicity First: Single entry point (New) for all protocol types
  2. Platform Awareness: Automatic protocol availability based on OS
  3. Type Safety: Configuration-based server creation with validation
  4. Consistent API: All servers implement socket.Server interface
  5. Zero Overhead: Factory only adds a single switch statement

Key Features

  • Unified API: Single New() function for all protocols
  • Platform-aware: Automatic Unix socket support detection
  • Type-safe configuration: Uses config.Server struct
  • Protocol validation: Returns error for unsupported protocols
  • Zero dependencies: Only delegates to sub-packages
  • Minimal overhead: Direct delegation without wrapping

Usage Examples

## TCP Server

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

func main() {
    handler := func(c socket.Context) {
        defer c.Close()
        // Handle connection...
    }

    cfg := config.Server{
        Network: protocol.NetworkTCP,
        Address: ":8080",
    }

    srv, err := server.New(nil, handler, cfg)
    if err != nil {
        panic(err)
    }

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

## UDP Server

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

srv, err := server.New(nil, handler, cfg)
if err != nil {
    panic(err)
}

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

## Unix Socket Server (Linux/Darwin only)

import "github.com/nabbar/golib/file/perm"

cfg := config.Server{
    Network:   protocol.NetworkUnix,
    Address:   "/tmp/app.sock",
    PermFile:  perm.Perm(0660),
    GroupPerm: -1,
}

srv, err := server.New(nil, handler, cfg)
if err != nil {
    panic(err)
}

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

Protocol Selection

The New() function selects the appropriate server implementation based on cfg.Network value:

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

Configuration

The New() function accepts a config.Server struct containing:

  • Network: Protocol type (NetworkTCP, NetworkUDP, NetworkUnix, etc.)
  • Address: Protocol-specific address string
  • TCP/UDP: "[host]:port" format
  • Unix: filesystem path
  • PermFile: File permissions for Unix sockets (ignored for TCP/UDP)
  • GroupPerm: Group ID for Unix socket ownership (ignored for TCP/UDP)
  • ConIdleTimeout: Idle timeout for connections (applies to all protocols)
  • TLS: TLS configuration (TCP only)

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

Error Handling

The New() function returns an error if:

  1. Protocol is not supported on the current platform Example: NetworkUnix on Windows returns ErrInvalidProtocol

  2. Protocol value is invalid or unrecognized Example: Undefined protocol constant returns ErrInvalidProtocol

  3. Sub-package constructor fails Example: tcp.New() fails due to invalid configuration

All errors are propagated from the underlying protocol implementation.

Platform Support

## Linux (//go:build linux)

  • Supported: TCP, TCP4, TCP6, UDP, UDP4, UDP6, Unix, UnixGram
  • Unix sockets: Full support with file permissions and group ownership
  • Special features: SCM_CREDENTIALS for process authentication

## Darwin/macOS (//go:build darwin)

  • Supported: TCP, TCP4, TCP6, UDP, UDP4, UDP6, Unix, UnixGram
  • Unix sockets: Full support with file permissions and group ownership
  • Special features: Standard Unix socket features

## Other Platforms (//go:build !linux && !darwin)

  • Supported: TCP, TCP4, TCP6, UDP, UDP4, UDP6
  • Unix sockets: Not supported (returns ErrInvalidProtocol)
  • Note: Includes Windows, BSD, Solaris, etc.

Thread Safety

The New() function is thread-safe and can be called concurrently from multiple goroutines. Each call creates a new, independent server instance with its own state and resources.

The returned socket.Server implementations are also thread-safe for concurrent method calls, but each connection is handled in its own goroutine.

Performance Considerations

## Factory Overhead

The server factory adds minimal overhead:

  • One switch statement on protocol type
  • One function call to the appropriate constructor
  • No additional memory allocations
  • No runtime reflection

Typical overhead: <1 microsecond per New() call.

## Protocol Performance Characteristics

┌──────────────┬──────────────┬─────────────┬──────────────────┐
│  Protocol    │  Throughput  │  Latency    │  Best Use Case   │
├──────────────┼──────────────┼─────────────┼──────────────────┤
│  TCP         │  High        │  Low        │  Network IPC     │
│  UDP         │  Very High   │  Very Low   │  Datagrams       │
│  Unix        │  Highest     │  Lowest     │  Local IPC       │
│  UnixGram    │  Highest     │  Lowest     │  Local datagrams │
└──────────────┴──────────────┴─────────────┴──────────────────┘

Limitations

  1. Factory Only: This package provides no direct functionality, only delegation
  2. Platform-Specific: Unix socket support depends on OS (Linux/Darwin only)
  3. No Protocol Mixing: Each server handles only one protocol type
  4. No Auto-Detection: Protocol must be explicitly specified in configuration
  5. No Fallback: If a protocol is unsupported, an error is returned (no fallback)

Best Practices

## 1. Use Appropriate Protocol for Use Case

// Local IPC between processes on same host
cfg.Network = protocol.NetworkUnix  // Lowest latency

// Network communication
cfg.Network = protocol.NetworkTCP   // Reliable, ordered

// Real-time datagrams (logging, metrics)
cfg.Network = protocol.NetworkUDP   // Fastest, connectionless

## 2. Handle Platform-Specific Errors

srv, err := server.New(nil, handler, cfg)
if err == config.ErrInvalidProtocol {
    // Protocol not supported on this platform
    // Fall back to TCP
    cfg.Network = protocol.NetworkTCP
    srv, err = server.New(nil, handler, cfg)
}

## 3. Configure Protocol-Specific Options

// TCP-specific: Enable TLS
if cfg.Network.IsTCP() {
    cfg.TLS.Enable = true
}

// Unix-specific: Set file permissions
if cfg.Network == protocol.NetworkUnix {
    cfg.PermFile = perm.Perm(0660)
}

## 4. Resource Management

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

if err := srv.Listen(ctx); err != nil {
    return err
}

## 5. Graceful Shutdown

srv, err := server.New(nil, handler, cfg)
if err != nil {
    return err
}

// Handle signals
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)

go func() {
    <-sigChan
    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()
    srv.Shutdown(ctx)
}()

srv.Listen(context.Background())

Comparison with Direct Protocol Packages

## Using Factory (server.New)

Advantages:

  • Single import for all protocols
  • Consistent API across protocols
  • Configuration-based server selection
  • Easier to switch protocols

Disadvantages:

  • Slight indirection overhead
  • Less explicit about protocol used

## Using Direct Protocol Packages

Advantages:

  • More explicit (tcp.New vs server.New)
  • Direct access to protocol-specific features
  • Slightly better IDE autocomplete

Disadvantages:

  • Multiple imports needed
  • More code changes when switching protocols
  • Repetitive error handling

Recommendation: Use server.New for most cases. Use protocol-specific packages when you need direct access to protocol-specific features or when protocol selection is static and won't change.

  • github.com/nabbar/golib/socket: Base interfaces and types
  • github.com/nabbar/golib/socket/config: Server configuration structures
  • github.com/nabbar/golib/socket/server/tcp: TCP server implementation
  • github.com/nabbar/golib/socket/server/udp: UDP server implementation
  • github.com/nabbar/golib/socket/server/unix: Unix socket server (Linux/Darwin)
  • github.com/nabbar/golib/socket/server/unixgram: Unix datagram server (Linux/Darwin)
  • github.com/nabbar/golib/network/protocol: Protocol constants and utilities

See Also

For detailed documentation on individual protocol implementations, refer to:

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

For examples, see example_test.go in this package.

Package server provides a unified factory for creating socket servers across different network protocols on Linux platforms.

This package serves as a convenience wrapper that creates appropriate server implementations based on the specified network protocol:

  • TCP, TCP4, TCP6: Connection-oriented network servers (see github.com/nabbar/golib/socket/server/tcp)
  • UDP, UDP4, UDP6: Connectionless datagram network servers (see github.com/nabbar/golib/socket/server/udp)
  • Unix: Connection-oriented UNIX domain socket servers (see github.com/nabbar/golib/socket/server/unix)
  • UnixGram: Connectionless UNIX datagram socket servers (see github.com/nabbar/golib/socket/server/unixgram)

All created servers implement the github.com/nabbar/golib/socket.Server interface, providing a consistent API regardless of the underlying protocol.

Example:

handler := func(r socket.Reader, w socket.Writer) {
    defer r.Close()
    defer w.Close()
    io.Copy(w, r) // Echo server
}

server, err := server.New(nil, handler, protocol.NetworkTCP, ":8080", 0, -1)
if err != nil {
    log.Fatal(err)
}
defer server.Close()

server.Listen(context.Background())
Example

Example demonstrates creating a basic TCP server using the factory. This is the simplest way to create a socket server.

package main

import (
	"context"
	"time"

	libptc "github.com/nabbar/golib/network/protocol"

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

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

	scksrv "github.com/nabbar/golib/socket/server"
)

func main() {
	// Create a simple echo handler
	handler := func(c libsck.Context) {
		defer func() { _ = c.Close() }()
		buf := make([]byte, 1024)
		for {
			n, err := c.Read(buf)
			if err != nil {
				return
			}
			if n > 0 {
				_, _ = c.Write(buf[:n])
			}
		}
	}

	// Create server configuration
	cfg := sckcfg.Server{
		Network: libptc.NetworkTCP,
		Address: ":8080",
	}

	// Create server using factory
	srv, err := scksrv.New(nil, handler, cfg)
	if err != nil {
		panic(err)
	}

	// Start server
	ctx := context.Background()
	go func() {
		_ = srv.Listen(ctx)
	}()

	// Wait for server to start
	time.Sleep(100 * time.Millisecond)

	// Shutdown after demonstration
	_ = srv.Shutdown(ctx)
}
Example (GracefulShutdown)

Example_gracefulShutdown demonstrates graceful server shutdown.

package main

import (
	"context"
	"fmt"
	"time"

	libptc "github.com/nabbar/golib/network/protocol"

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

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

	scksrv "github.com/nabbar/golib/socket/server"
)

func main() {
	handler := func(c libsck.Context) {
		defer func() { _ = c.Close() }()
		time.Sleep(100 * time.Millisecond)
	}

	cfg := sckcfg.Server{
		Network: libptc.NetworkTCP,
		Address: ":9200",
	}

	srv, err := scksrv.New(nil, handler, cfg)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	// Start server
	ctx := context.Background()
	go func() {
		_ = srv.Listen(ctx)
	}()

	// Wait for server to start
	time.Sleep(50 * time.Millisecond)

	// Graceful shutdown with timeout
	shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	err = srv.Shutdown(shutdownCtx)
	if err == nil {
		fmt.Println("Server shut down gracefully")
	}

}
Output:

Server shut down gracefully
Example (MultipleServers)

Example_multipleServers demonstrates running multiple servers with different protocols.

package main

import (
	"context"
	"fmt"
	"time"

	libptc "github.com/nabbar/golib/network/protocol"

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

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

	scksrv "github.com/nabbar/golib/socket/server"
)

func main() {
	handler := func(c libsck.Context) {
		defer func() { _ = c.Close() }()
	}

	// Create TCP server
	tcpCfg := sckcfg.Server{
		Network: libptc.NetworkTCP,
		Address: ":9100",
	}
	tcpSrv, err := scksrv.New(nil, handler, tcpCfg)
	if err != nil {
		fmt.Printf("TCP Error: %v\n", err)
		return
	}

	// Create UDP server
	udpCfg := sckcfg.Server{
		Network: libptc.NetworkUDP,
		Address: ":9101",
	}
	udpSrv, err := scksrv.New(nil, handler, udpCfg)
	if err != nil {
		fmt.Printf("UDP Error: %v\n", err)
		return
	}

	fmt.Println("Multiple servers created successfully")

	// Start both servers
	ctx := context.Background()
	go func() {
		_ = tcpSrv.Listen(ctx)
	}()
	go func() {
		_ = udpSrv.Listen(ctx)
	}()

	// Wait and shutdown
	time.Sleep(50 * time.Millisecond)
	_ = tcpSrv.Shutdown(ctx)
	_ = udpSrv.Shutdown(ctx)

}
Output:

Multiple servers created successfully

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func New

New creates a new socket server based on the specified network protocol.

This factory function instantiates the appropriate server implementation for the given protocol type. On Linux platforms, all protocol types are supported, including UNIX domain sockets.

Parameters:

  • upd: Optional callback function invoked for each new connection (TCP/Unix) or when the socket is created (UDP/Unixgram). Can be used to set socket options like timeouts, buffer sizes, etc. Pass nil if not needed.
  • handler: Required function to process connections or datagrams. For connection-oriented protocols (TCP/Unix), it's called for each connection. For datagram protocols (UDP/Unixgram), it handles all incoming datagrams. The signature is: func(socket.Reader, socket.Writer)
  • proto: Network protocol from github.com/nabbar/golib/network/protocol. Supported values on Linux:
  • NetworkTCP, NetworkTCP4, NetworkTCP6: TCP servers
  • NetworkUDP, NetworkUDP4, NetworkUDP6: UDP servers
  • NetworkUnix: UNIX domain stream socket servers
  • NetworkUnixGram: UNIX domain datagram socket servers
  • address: Protocol-specific address string:
  • TCP/UDP: "[host]:port" format (e.g., ":8080", "0.0.0.0:8080", "localhost:9000")
  • UNIX: filesystem path (e.g., "/tmp/app.sock", "/var/run/app.sock")
  • perm: File permissions for UNIX socket files (e.g., 0600, 0660, 0666). Only applies to NetworkUnix and NetworkUnixGram. Ignored for TCP/UDP. If set to 0, default permissions (0770) are applied.
  • gid: Group ID for UNIX socket file ownership. Only applies to NetworkUnix and NetworkUnixGram. Use -1 for the process's current group, or specify a group ID (0-32767). Ignored for TCP/UDP.

Returns:

  • libsck.Server: A server instance implementing the socket.Server interface
  • error: An error if the protocol is invalid, address validation fails, or server configuration fails

Example:

// TCP server
handler := func(r socket.Reader, w socket.Writer) {
    defer r.Close()
    defer w.Close()
    // Handle connection...
}

server, err := New(nil, handler, protocol.NetworkTCP, ":8080", 0, -1)
if err != nil {
    log.Fatal(err)
}

// UNIX socket server with permissions
unixServer, err := New(nil, handler, protocol.NetworkUnix, "/tmp/app.sock", 0600, -1)
if err != nil {
    log.Fatal(err)
}
Example

ExampleNew demonstrates creating a TCP server using the factory.

package main

import (
	"fmt"
	"io"

	libptc "github.com/nabbar/golib/network/protocol"

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

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

	scksrv "github.com/nabbar/golib/socket/server"
)

func main() {
	// Define connection handler
	handler := func(c libsck.Context) {
		defer func() { _ = c.Close() }()
		_, _ = io.Copy(c, c) // Echo
	}

	// Create configuration
	cfg := sckcfg.Server{
		Network: libptc.NetworkTCP,
		Address: ":9000",
	}

	// Create server using factory
	srv, err := scksrv.New(nil, handler, cfg)
	if err != nil {
		fmt.Printf("Failed to create server: %v\n", err)
		return
	}

	fmt.Printf("Server created successfully\n")
	_ = srv
}
Output:

Server created successfully
Example (InvalidProtocol)

ExampleNew_invalidProtocol demonstrates error handling for invalid protocols.

package main

import (
	"fmt"

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

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

	scksrv "github.com/nabbar/golib/socket/server"
)

func main() {
	handler := func(c libsck.Context) {
		defer func() { _ = c.Close() }()
	}

	// Use an invalid protocol value
	cfg := sckcfg.Server{
		Network: 255, // Invalid protocol
		Address: ":9007",
	}

	srv, err := scksrv.New(nil, handler, cfg)
	if err != nil {
		fmt.Println("Error: invalid protocol")
	}
	_ = srv
}
Output:

Error: invalid protocol
Example (Tcp)

ExampleNew_tcp demonstrates creating a TCP server.

package main

import (
	"fmt"

	libptc "github.com/nabbar/golib/network/protocol"

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

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

	scksrv "github.com/nabbar/golib/socket/server"
)

func main() {
	handler := func(c libsck.Context) {
		defer func() { _ = c.Close() }()
	}

	cfg := sckcfg.Server{
		Network: libptc.NetworkTCP,
		Address: ":9001",
	}

	srv, err := scksrv.New(nil, handler, cfg)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	fmt.Println("TCP server created")
	_ = srv
}
Output:

TCP server created
Example (Tcp4)

ExampleNew_tcp4 demonstrates creating a TCP4 server (IPv4 only).

package main

import (
	"fmt"

	libptc "github.com/nabbar/golib/network/protocol"

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

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

	scksrv "github.com/nabbar/golib/socket/server"
)

func main() {
	handler := func(c libsck.Context) {
		defer func() { _ = c.Close() }()
	}

	cfg := sckcfg.Server{
		Network: libptc.NetworkTCP4,
		Address: ":9002",
	}

	srv, err := scksrv.New(nil, handler, cfg)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	fmt.Println("TCP4 server created")
	_ = srv
}
Output:

TCP4 server created
Example (Tcp6)

ExampleNew_tcp6 demonstrates creating a TCP6 server (IPv6 only).

package main

import (
	"fmt"

	libptc "github.com/nabbar/golib/network/protocol"

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

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

	scksrv "github.com/nabbar/golib/socket/server"
)

func main() {
	handler := func(c libsck.Context) {
		defer func() { _ = c.Close() }()
	}

	cfg := sckcfg.Server{
		Network: libptc.NetworkTCP6,
		Address: ":9003",
	}

	srv, err := scksrv.New(nil, handler, cfg)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	fmt.Println("TCP6 server created")
	_ = srv
}
Output:

TCP6 server created
Example (Udp)

ExampleNew_udp demonstrates creating a UDP server.

package main

import (
	"fmt"

	libptc "github.com/nabbar/golib/network/protocol"

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

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

	scksrv "github.com/nabbar/golib/socket/server"
)

func main() {
	handler := func(c libsck.Context) {
		defer func() { _ = c.Close() }()
	}

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

	srv, err := scksrv.New(nil, handler, cfg)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	fmt.Println("UDP server created")
	_ = srv
}
Output:

UDP server created
Example (Udp4)

ExampleNew_udp4 demonstrates creating a UDP4 server (IPv4 only).

package main

import (
	"fmt"

	libptc "github.com/nabbar/golib/network/protocol"

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

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

	scksrv "github.com/nabbar/golib/socket/server"
)

func main() {
	handler := func(c libsck.Context) {
		defer func() { _ = c.Close() }()
	}

	cfg := sckcfg.Server{
		Network: libptc.NetworkUDP4,
		Address: ":9005",
	}

	srv, err := scksrv.New(nil, handler, cfg)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	fmt.Println("UDP4 server created")
	_ = srv
}
Output:

UDP4 server created
Example (Udp6)

ExampleNew_udp6 demonstrates creating a UDP6 server (IPv6 only).

package main

import (
	"fmt"

	libptc "github.com/nabbar/golib/network/protocol"

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

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

	scksrv "github.com/nabbar/golib/socket/server"
)

func main() {
	handler := func(c libsck.Context) {
		defer func() { _ = c.Close() }()
	}

	cfg := sckcfg.Server{
		Network: libptc.NetworkUDP6,
		Address: ":9006",
	}

	srv, err := scksrv.New(nil, handler, cfg)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	fmt.Println("UDP6 server created")
	_ = srv
}
Output:

UDP6 server created
Example (WithIdleTimeout)

ExampleNew_withIdleTimeout demonstrates configuring idle timeout.

package main

import (
	"fmt"

	libdur "github.com/nabbar/golib/duration"
	libptc "github.com/nabbar/golib/network/protocol"

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

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

	scksrv "github.com/nabbar/golib/socket/server"
)

func main() {
	handler := func(c libsck.Context) {
		defer func() { _ = c.Close() }()
	}

	cfg := sckcfg.Server{
		Network:        libptc.NetworkTCP,
		Address:        ":9008",
		ConIdleTimeout: libdur.Minutes(5),
	}

	srv, err := scksrv.New(nil, handler, cfg)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	fmt.Println("Server with idle timeout created")
	_ = srv
}
Output:

Server with idle timeout created

Types

This section is empty.

Directories

Path Synopsis
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.
Package udp provides a UDP server implementation with connectionless datagram support.
Package udp provides a UDP server implementation with connectionless datagram support.
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.
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