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

Simple Tcp Client Laravel Package

spatie/simple-tcp-client

Simple TCP client for PHP/Laravel: connect to a host/port, send data, and receive responses with a clean API. Useful for interacting with TCP services (SMTP, HTTP, custom servers), testing network protocols, and building lightweight clients.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require spatie/simple-tcp-client
    

    No additional configuration is required—just autoload the package.

  2. First Use Case: Connect to a TCP server (e.g., SMTP, FTP, or a custom service) and exchange data:

    use Spatie\SimpleTcpClient\TcpClient;
    
    $client = new TcpClient('host.example.com', 1234);
    $client->connect();
    
    // Send a command (e.g., SMTP EHLO)
    $client->send("EHLO example.com\r\n");
    
    // Receive response
    $response = $client->receive();
    echo $response; // Parse server response
    
    $client->close();
    
  3. Where to Look First:

    • TcpClient class: Core functionality for connections, sending/receiving data.
    • connect()/close(): Manage connection lifecycle.
    • send()/receive(): Core methods for TCP communication.
    • Tests: GitHub Actions for edge cases (timeouts, malformed data).

Implementation Patterns

Usage Patterns

  1. Connection Management:

    • Use try-catch with connect() to handle connection failures gracefully:
      try {
          $client->connect();
          // Proceed with communication
      } catch (\Spatie\SimpleTcpClient\Exceptions\ConnectionFailed $e) {
          Log::error("TCP connection failed: " . $e->getMessage());
      }
      
  2. Protocol-Specific Workflows:

    • SMTP/IMAP: Chain send()/receive() calls for multi-step protocols:
      $client->send("AUTH LOGIN\r\n");
      $client->send(base64_encode($username) . "\r\n");
      $client->send(base64_encode($password) . "\r\n");
      
    • Binary Data: Use sendRaw() for non-text protocols (e.g., FTP, custom binary APIs):
      $client->sendRaw($binaryPayload);
      
  3. Timeout Handling:

    • Set timeouts during initialization to avoid hanging:
      $client = new TcpClient('host.example.com', 1234, [
          'timeout' => 5.0, // 5 seconds
      ]);
      
  4. Reusable Client Instances:

    • For long-lived connections (e.g., WebSocket-like interactions), reuse the TcpClient:
      $client = new TcpClient('host.example.com', 8080);
      $client->connect();
      
      while ($data = $client->receive()) {
          // Process data in a loop
      }
      
  5. Integration with Laravel:

    • Queue Jobs: Offload TCP operations to queues:
      dispatch(new SendTcpCommandJob($host, $port, $payload));
      
    • Service Providers: Bind the client for dependency injection:
      $this->app->bind(TcpClient::class, function ($app) {
          return new TcpClient(config('tcp.host'), config('tcp.port'));
      });
      
  6. Testing:

    • Mock TcpClient in unit tests using Laravel’s Mockery:
      $mock = Mockery::mock(TcpClient::class);
      $mock->shouldReceive('receive')->andReturn('220 Ready');
      

Gotchas and Tips

Pitfalls

  1. Connection State:

    • Error: Calling send()/receive() without connect() throws exceptions. Always verify the connection state:
      if (!$client->isConnected()) {
          $client->connect();
      }
      
    • Fix: Use try-catch blocks or check isConnected() before operations.
  2. Timeouts:

    • Error: Long-running operations may exceed default timeouts (e.g., large file transfers).
    • Fix: Explicitly set timeouts in the constructor or use setTimeout():
      $client->setTimeout(30.0); // 30 seconds
      
  3. Buffering Issues:

    • Error: receive() may return partial data if the server sends responses in chunks.
    • Fix: Implement a loop to read until a delimiter (e.g., \r\n) or EOF:
      $response = '';
      while (($chunk = $client->receive()) && strpos($chunk, "\r\n") === false) {
          $response .= $chunk;
      }
      
  4. Resource Leaks:

    • Error: Forgetting to call close() can lead to open sockets consuming resources.
    • Fix: Use a finally block or Laravel’s illuminate/support/Traits/ManagesFluentMethods for automatic cleanup:
      try {
          $client->connect();
          // ...
      } finally {
          $client->close();
      }
      
  5. Protocol-Specific Delimiters:

    • Error: Misinterpreting server responses (e.g., SMTP’s multi-line replies).
    • Fix: Parse responses manually or use a helper method:
      private function parseSmtpResponse(string $response): array {
          return explode("\r\n", $response);
      }
      

Tips

  1. Logging:

    • Log raw send()/receive() data for debugging:
      Log::debug('TCP Send:', ['data' => $payload]);
      Log::debug('TCP Receive:', ['data' => $response]);
      
  2. Configuration:

    • Store host/port in config/tcp.php for easy maintenance:
      return [
          'host' => env('TCP_HOST', 'localhost'),
          'port' => env('TCP_PORT', 1234),
          'timeout' => 10.0,
      ];
      
  3. Extending Functionality:

    • Custom Exceptions: Extend the base exception class for domain-specific errors:
      class TcpProtocolException extends \Spatie\SimpleTcpClient\Exceptions\ConnectionException {}
      
    • Decorators: Wrap TcpClient to add retries or logging:
      class LoggingTcpClient extends TcpClient {
          public function send(string $data) {
              Log::info('Sending: ' . $data);
              return parent::send($data);
          }
      }
      
  4. Performance:

    • For high-throughput applications, minimize connect()/close() calls by reusing connections.
    • Use sendRaw() for binary data to avoid encoding overhead.
  5. Security:

    • Validate server responses to prevent injection (e.g., SMTP command injection):
      if (!preg_match('/^[A-Za-z0-9\s]+$/', $response)) {
          throw new \InvalidArgumentException("Invalid server response");
      }
      
  6. Testing:

    • Use spatie/fake-server to simulate TCP servers in tests:
      $fakeServer = new FakeServer();
      $fakeServer->onReceive(fn ($data) => "ACK $data");
      $client->connect($fakeServer->getHost(), $fakeServer->getPort());
      
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport