Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Socket Laravel Package

amphp/socket

Async, non-blocking socket library for AMPHP. Provides client/server abstractions over TCP, UDP, and Unix domain sockets with DNS resolution, retries, connect timeouts, cancellation, and optional TLS encryption. Implements ReadableStream/WritableStream.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require amphp/socket
    

    Ensure ext-sockets and ext-openssl are enabled in your PHP environment.

  2. First Use Case: Basic TCP Client

    use Amp\Socket;
    use function Amp\Socket\connect;
    
    $socket = connect('example.com:80');
    $socket->write("GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n");
    $response = $socket->read();
    $socket->close();
    
  3. First Use Case: Basic TCP Server

    use Amp\Socket;
    use function Amp\Socket\listen;
    
    $server = Socket\listen('127.0.0.1:8080');
    while ($client = $server->accept()) {
        $client->write("HTTP/1.1 200 OK\r\n\r\nHello, World!");
        $client->close();
    }
    

Where to Look First

  • Documentation: Start with the Amp v3 Socket documentation for conceptual overviews.
  • Examples: Explore the examples/ directory in the repository for practical use cases (e.g., HTTP client/server, UDP sockets).
  • API Reference: Focus on:
    • Amp\Socket\connect() and Amp\Socket\connectTls() for clients.
    • Amp\Socket\listen() and ServerSocket for servers.
    • ReadableStream/WritableStream interfaces for data handling.

Implementation Patterns

Core Workflows

1. Client-Side Patterns

  • Connection Handling: Use ConnectContext to configure timeouts, DNS resolution, and TLS:
    $context = (new Amp\Socket\ConnectContext)
        ->withConnectTimeout(2.0)
        ->withTlsContext(new Amp\Socket\ClientTlsContext('example.com'));
    $socket = connect('example.com:443', $context);
    
  • Async Data Flow: Pipe data between streams using Amp\ByteStream\pipe():
    use Amp\ByteStream;
    ByteStream\pipe($socket, ByteStream\getStdout());
    
  • Cancellation: Use Amp\DeferredCancellation to abort pending connections:
    $cancellation = (new Amp\DeferredCancellation())->getCancellation();
    $socket = connect('example.com:80', null, $cancellation);
    $cancellation->cancel(); // Aborts the connection.
    

2. Server-Side Patterns

  • Accepting Connections: Use a while loop with ServerSocket::accept() in a coroutine:
    while ($client = $server->accept()) {
        Amp\async(function () use ($client) {
            // Handle client in a separate fiber.
            $client->write("Welcome!\r\n");
            $client->close();
        });
    }
    
  • TLS Setup: Configure TLS after accepting a connection:
    $tlsContext = new Amp\Socket\ServerTlsContext(
        __DIR__ . '/cert.pem',
        __DIR__ . '/key.pem'
    );
    $socket->setupTls($tlsContext);
    
  • Address Binding: Use listen() with BindContext for customization:
    $bindContext = (new Amp\Socket\BindContext)
        ->withReuseAddress(true);
    $server = Socket\listen('127.0.0.1:0', $bindContext);
    

3. UDP Patterns

  • Binding and Sending:
    $udpSocket = Amp\Socket\bindUdpSocket('127.0.0.1:0');
    $udpSocket->send('Hello UDP!', '127.0.0.1:9999');
    
  • Receiving:
    $message = $udpSocket->receive();
    

4. Proxy Support

  • SOCKS5 Proxy:
    $connector = new Amp\Socket\Socks5SocketConnector(
        'proxy.example.com:1080',
        'username',
        'password'
    );
    $socket = $connector->connect('example.com:80');
    

Integration Tips

  • Laravel Integration: Use Amp\Loop with Laravel's event loop (e.g., spatie/laravel-amp) for async tasks:
    use Amp\Loop;
    use Spatie\LaravelAmp\Amp;
    
    Amp::run(function () {
        $socket = connect('example.com:80');
        // Handle socket...
    });
    
  • Dependency Injection: Bind Amp\Socket\SocketConnector interfaces to concrete implementations (e.g., DnsSocketConnector) in Laravel's service container:
    $this->app->bind(
        Amp\Socket\SocketConnector::class,
        Amp\Socket\DnsSocketConnector::class
    );
    
  • Error Handling: Wrap socket operations in try-catch blocks for Amp\Socket\ConnectException or Amp\Socket\BindException:
    try {
        $socket = connect('invalid-host:80');
    } catch (Amp\Socket\ConnectException $e) {
        Log::error('Connection failed:', ['error' => $e->getMessage()]);
    }
    

Gotchas and Tips

Pitfalls

  1. TLS Handshake Timing:

    • Issue: Data sent before setupTls() completes is transmitted in plaintext.
    • Fix: Ensure TLS is established before writing sensitive data:
      $socket->setupTls($tlsContext)->then(function () use ($socket) {
          $socket->write("Secure data...");
      });
      
  2. Blocking Operations:

    • Issue: Long-running operations in accept() or read() block the event loop.
    • Fix: Offload work to fibers using Amp\async():
      while ($client = $server->accept()) {
          Amp\async(function () use ($client) {
              // Non-blocking logic here.
          });
      }
      
  3. Resource Leaks:

    • Issue: Unclosed sockets or servers consume file descriptors.
    • Fix: Always call close() or end():
      $socket->end(); // Ensures pending writes are flushed.
      
  4. DNS Resolution:

    • Issue: DnsSocketConnector fails silently on DNS errors in some PHP versions.
    • Fix: Use RetrySocketConnector for retries:
      $retryConnector = new Amp\Socket\RetrySocketConnector(
          new Amp\Socket\DnsSocketConnector(),
          3 // Max retries
      );
      
  5. UDP Chunk Sizes:

    • Issue: Large UDP packets may be truncated.
    • Fix: Use ResourceUdpSocket with default chunk size (576 bytes):
      $udpSocket = Amp\Socket\bindUdpSocket('127.0.0.1:0', 1024); // Custom chunk size.
      

Debugging Tips

  1. Stack Traces:

    • Enable Amp\Loop::run() with Amp\Loop::SET_ASYNC_SIGNAL_HANDLER for better error traces:
      Amp\Loop::run(function () {
          // Your code.
      }, Amp\Loop::SET_ASYNC_SIGNAL_HANDLER);
      
  2. Socket State:

    • Check socket state with $socket->isReadable() or $socket->isWritable() before operations.
  3. Logging:

    • Log connection events and errors:
      $server->on('accept', function ($client) {
          Log::info('New connection from ' . $client->getRemoteAddress());
      });
      

Extension Points

  1. Custom Connectors:

    • Implement Amp\Socket\SocketConnector for custom protocols (e.g., HTTP/3):
      class CustomConnector implements Amp\Socket\SocketConnector {
          public function connect(string $address, ?Amp\Socket\ConnectContext $context = null): Amp\Socket\Socket {
              // Custom logic.
          }
      }
      
  2. Protocol Handlers:

    • Extend Amp\ByteStream\ReadableStream/WritableStream for custom framing (e.g., Protocol Buffers):
      class ProtobufStream implements Amp\ByteStream\ReadableStream {
          public function read(): Amp\ByteStream\ReadableStreamResult {
              // Decode protobuf messages.
          }
      }
      
  3. TLS Customization:

    • Extend Amp\Socket\ClientTlsContext or `ServerTlsContext
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle