2016-04-09 28 views
7

Devo collegare un server remoto con connessione socket asincrona e dati reteive. Posso collegarmi ma c'è un problema.Dimensione buffer client socket asincrono

I pacchetti vengono inviati a pezzi. Ho due opzioni; Posso impostare un buffer e ottenere tutto il pacchetto in un unico pezzo o combinare pezzi quando tutti i trasferimenti effettuati. Penso che la prima opzione (cosa tampone) sia la strada giusta.

Sto definendo una dimensione del buffer ma non funziona nella prima parte. In altre parti, funziona ma con questo metodo non riesco a ottenere l'intero pacchetto in un unico pezzo perché la prima parte è limitata con 5,24 Kb.

Potete trovare il mio codice qui sotto:

$loop = React\EventLoop\Factory::create(); 

     $dnsResolverFactory = new React\Dns\Resolver\Factory(); 
     $dns = $dnsResolverFactory->createCached('8.8.8.8', $loop); 
     $connector = new React\SocketClient\Connector($loop, $dns); 
     $connector->create(ENDPOINT_IP , ENDPOINT_PORT)->then(function (React\Stream\Stream $stream) use ($loop) { 

      $command = '{C:"EL",bmId:43,inst:"my_instance",tok:"my_token"}'; 

      $command_length = strlen($command); 
      $command_length = pack("N", $command_length); 

      $stream->write($command_length); 
      $stream->write($command); 

      $stream->bufferSize = 999999; 
      $stream->on('data', function ($data) { 

      $package = substr($data, 0, 4); 
      $unpack  = unpack('N', $package); // I'm getting whole package size 

      echo $data; 



      }); 


     }); 

     $loop->run(); 

ho cercato di definire una dimensione del buffer sotto $stream->on('data', function ($data) { linea, ma come si indovina è fallito. Non so come gestirlo nel modo giusto.

Grazie in anticipo.

risposta

4

"Posso impostare un buffer e ottenere tutto il pacchetto in un unico pezzo o combinare i pezzi quando tutto il trasferimento è fatto. Penso che la prima opzione (buffer cosa) sia la strada giusta."

La prima opzione è non nel modo giusto, semplicemente perché non è il modo in cui funziona la comunicazione socket.

Se si ricevono, ad esempio, 5 kB di dati e si imposta il buffer in modo che sia sufficientemente grande, diciamo 10 kB, non è possibile aspettarsi che in una chiamata a $stream->on('data', function ($data) { ... si ricevano tutti i 5 kB.

È necessario fare tre cose:

  • È necessario conoscere l'esatta dimensione dei dati che si ricevono in un unico blocco di segnalazione. O si sa che il messaggio avrà sempre una dimensione fissa e nota, oppure il blocco dati ha un'intestazione da cui è possibile leggere la lunghezza del messaggio. Nel tuo caso stai leggendo la dimensione del messaggio dai primi 4 byte dei dati ricevuti.
  • Nel ciclo è necessario leggere i blocchi di dati che provengono dal server e concatenarli finché non si dispone di abbastanza byte per leggere la dimensione dell'intero messaggio. Nel tuo caso questo è 4 byte. Tuttavia, sembra strano, c'è la possibilità che tu riceva 1 e poi 3 byte in due blocchi, in due chiamate allo $stream->on('data', function ($data) { .... Quando la dimensione dei dati concatenati è >=4, leggi la dimensione del messaggio.
  • Nello stesso ciclo, è necessario continuare a leggere i blocchi di dati che provengono dal socket e concatenarli finché non si ricevono tutti i byte del messaggio. Ovviamente, questo significa che è necessario avere una variabile definita al di fuori del ciclo in cui verranno memorizzati i dati ricevuti. Dopo aver ricevuto l'intero messaggio, è necessario uscire dal ciclo.

La buona idea è quella di impostare un timer per il ciclo in modo da poter attendere che l'intero messaggio venga ricevuto per un periodo di tempo limitato. Potrebbe accadere che la connessione tra client e server si interrompa durante la trasmissione e se non si dispone di una logica di timeout il loop attenderà per sempre l'intero messaggio da ricevere.

+0

In realtà ho provato un sacco di cose compresi i vostri suggerimenti ma il risultato è lo stesso. –

+0

Hm, non hai specificato quale problema esatto hai. Si prega di inviare ciò che si riceve come risultato e cosa è previsto. Se si ricevono più pacchetti di una risposta uno in uno, è necessario disporre di una logica aggiuntiva. Quando tutti i dati per un pacchetto sono arrivati ​​di solito, riceverete una parte del pacchetto successivo nella stessa risposta. Questi dati in eccesso che devi salvare e utilizzare nella prossima iterazione come dati di partenza. – BJovke