Domanda

Ho letto un esempio di Tcp Echo Server e alcune cose non sono chiare per me.

TcpClient client = null;
NetworkStream netStream = null;

try {
  client = listener.AcceptTcpClient(); 
  netStream = client.GetStream();

  int totalBytesEchoed = 0;
  while ((bytesRcvd = netStream.Read(rcvBuffer, 0, rcvBuffer.Length)) > 0) {
    netStream.Write(rcvBuffer, 0, bytesRcvd);
    totalBytesEchoed += bytesRcvd;
  }

  netStream.Close();
  client.Close();
} catch {
  netStream.Close();
}

Quando il server riceve un pacchetto (il ciclo while), legge i dati in rcvBuffer e li scrive nello stream.

Ciò che mi confonde è l'ordine cronologico dei messaggi nella comunicazione. I dati scritti con netStream.Write () sono stati inviati immediatamente al client (che potrebbe anche essere ancora in fase di invio) o solo dopo l'elaborazione dei dati già scritti nel flusso (dal client).

La seguente domanda potrebbe anche chiarire la precedente: se un client invia alcuni dati scrivendo allo stream, i dati vengono spostati nella coda dei messaggi sul lato server in attesa di essere letti in modo che lo stream sia effettivamente "vuoto"? Ciò spiegherebbe perché il server può scrivere immediatamente nello stream - perché i dati che provengono dallo stream sono effettivamente bufferizzati altrove ...?

È stato utile?

Soluzione

Suggerimento: il metodo chiamato NetworkStream.Read sta bloccando in questo esempio.

Il libro è assolutamente corretto: l'accesso non elaborato ai flussi TCP non implica alcun tipo di "chunking extra"; e, in questo esempio, ad esempio, un singolo byte potrebbe essere facilmente elaborato alla volta. Tuttavia, eseguire la lettura e la scrittura in batch (normalmente con buffer esposti) può consentire un'elaborazione più efficiente (spesso a causa di meno chiamate di sistema). Il livello di rete e l'hardware di rete impiegano anche le proprie forme di buffer.

In realtà non esiste alcuna garanzia che i dati scritti da Write () vengano effettivamente scritti prima che più Reads () vengano completati correttamente: anche se i dati vengono scaricati in un livello, ciò non implica che vengano scaricati in un altro e non vi è assolutamente alcuna garanzia che i dati sono tornati al client. È qui che entrano in gioco protocolli di livello superiore.

Con questo esempio di eco i dati vengono semplicemente trasferiti il ??più velocemente possibile. Sia la scrittura che la lettura si bloccano in base allo stack di rete sottostante (in particolare i buffer di invio e ricezione), ciascuno con le proprie serie di buffer.

[Ciò semplifica un po 'le cose ovviamente - si potrebbe sempre guardare al TCP [protocollo] stesso che impone le caratteristiche di trasmissione sul flusso di pacchetti effettivo.]

Altri suggerimenti

Una connessione TCP è, in linea di principio, full duplex. Quindi hai a che fare con 2 canali separati e sì, entrambe le parti potrebbero scrivere contemporaneamente.

Tecnicamente hai ragione quando esegui l'operazione Read (), non stai leggendo i bit dal filo. Stai fondamentalmente leggendo i dati bufferizzati (blocchi ricevuti da un TCP e disposti in un ordine corretto). Quando ti invii puoi Flush () che in teoria dovrebbe inviare immediatamente i dati, ma i moderni stack TCP hanno un po 'di logica su come raccogliere i dati in pacchetti di dimensioni appropriate e farli scoppiare sul filo.

Come spiegato da Henk Holterman, TCP è un protocollo full duplex (se supportato da tutte le infrastrutture sottostanti), quindi l'invio e la ricezione di dati è maggiore di quando il server / client legge e scrive i dati. Non è come quando il server invia i dati, un client li leggerà immediatamente. Il client può inviare i propri dati e quindi eseguire Read (), in questo caso i dati rimarranno nel buffer di rete più a lungo e possono essere eliminati dopo qualche tempo in cui nessuno vuole leggerli. Almeno l'ho sperimentato quando ho a che fare con la mia libreria client / server supa dupa (-.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top