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 ¶
- Unified Interface: All socket types implement common interfaces (Server, Client, Context)
- Platform Awareness: Automatic protocol availability based on operating system
- Type Safety: Configuration-driven construction with compile-time validation
- Performance First: Zero-copy operations and minimal allocations where possible
- Production Ready: Built-in error handling, logging, and monitoring capabilities
- Concurrent by Design: Thread-safe operations with atomic state management
- 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:
- Return Values: All operations return Go standard errors
- Error Callbacks: Register FuncError for async error notification
- Error Filtering: ErrorFilter() removes expected errors (closed connections)
- 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 ¶
- Unix Sockets: Only available on Linux and Darwin (macOS)
- TLS Support: Only available for TCP-based protocols
- Multicast: Not directly supported (use raw sockets if needed)
- Protocol Mixing: Each socket handles only one protocol type
- Message Boundaries: TCP/Unix are stream-based (use delimiters or length prefixes)
Related Packages ¶
- 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 ¶
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.
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
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 )
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
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
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
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. |