2009-04-15 24 views
5

Sto provando ad utilizzare alcuni programmi di rete socket in C++. Sto cercando di inviare il testo "Hello World!" a un server che usa la funzione C++ send(). Inizialmente, ho impostato il buffer sulla dimensione di 13 da "Hello World!" complessivamente è di 12 caratteri (devi renderlo uno in più rispetto al numero di caratteri). La funzione di invio invia i caratteri al server solo se la invio circa 7 volte. E quando finalmente arriva al server, assomiglia a questo:Presa C++ Buffer da 256 byte

"Ciao mondo! Ciao mondo! Ciao mondo! Ciao mondo! Ciao mondo! Ciao mondo! Ciao mondo!"

Ora ecco la parte divertente. Il "Ciao mondo!" la frase invia immediatamente se imposto la dimensione del buffer su 256 (char buffer [256];). Quando si tratta del server, però, mostra "Hello World!" con un sacco di spazio dopo le due parole. Perché sta succedendo questo e se possibile, come posso risolverlo? Per favore mi faccia sapere.

Grazie

+0

Hai annullato la stringa? "Hello World! \ 0" – Alan

risposta

7

Quando si chiama read (o receive) con il tampone per leggere dalla presa, un valore intero viene restituito che specifica il numero di byte letti. Dovresti prenderne solo una parte dal buffer. Il resto è irrilevante:

int count = read(...); 
// buffer[0 .. count - 1] contains the appropriate data. 
+0

E solo per farti sapere, il server che riceve i dati è fatto in C# – QAH

+0

QAH: Questo vale anche per i socket C#, metodo Socket.Receive. –

4

buffer esistono per memorizzare i dati fino a quando si è pronti a inviarlo. Si dispone di una dimensione del buffer di invio pari a 256. Fino a quando non vengono trasmessi 256 caratteri attraverso il buffer, i dati non verranno inviati all'altro lato. Puoi risolvere questo problema chiamando un metodo flush sul tuo buffer quando sai di essere pronto per l'invio.

Per essere chiari, si esegue il buffering internamente, quindi il sistema operativo (o la libreria) esegue nuovamente il buffering quando si chiama send() e si passano alcuni dati.

Se si ottiene più specifico con quale libreria si sta utilizzando e magari si include uno snippet di codice, è probabile che si possa trovare la funzione di svuotamento del buffer corretta per l'invio.

In alternativa, se si è in * nix, basta disattivare l'algoritmo di Nagle in modo che il sistema operativo non bufferizzerà i piccoli pacchetti. Oppure, quando si imposta il socket, assicurarsi di utilizzare l'opzione TCP_NODELAY

6

L'algoritmo di Nagle di solito è attivato per impostazione predefinita. Questo combinerà diversi piccoli pacchetti in uno solo. Disattivando l'algoritmo di Nagle sarà possibile inviare immediatamente piccoli pacchetti.

0

Supponendo che questo sia un socket SOCK_STREAM, la cosa importante da tenere presente è che il protocollo TCP sottostante non mantiene alcun limite di segmento. Cioè, quando chiamate send() più volte, tutti i dati inviati possono essere facilmente restituiti da una singola chiamata recv() all'altra estremità. Oppure, i dati inviati in una chiamata send() possono essere restituiti in più recv() nell'altra estremità, ad es. se alcuni pacchetti sono stati ritardati a causa della congestione della rete. Questo è fondamentale per la progettazione di TCP e la tua applicazione deve essere progettata di conseguenza.

Inoltre, come rilevato da Mehrdad, la chiamata recv() restituisce il numero di byte letti dal cavo. Qualunque cosa dopo quel punto nel buffer è spazzatura e i dati non sono terminati a zero.

Un socket SOCK_DGRAM utilizza UDP al di sotto, che è interamente orientato ai pacchetti, al contrario di TCP orientato al flusso. Tuttavia, UDP non garantisce l'affidabilità (la U sta per Inaffidabile), quindi devi gestire tu stesso i pacchetti persi, duplicati, fuori ordine ecc. Questo è molto più difficile di I/O orientato al flusso.

+0

UDP è l'User Datagram Protocol - non ha nulla di inaffidabile nel suo nome. Hai ragione che è relativamente inaffidabile, però :) –

0

La programmazione delle prese è noiosa, soggetta a errori e non portabile.Inizia a utilizzare librerie come Boost o ACE che ti proteggono dalle API C di basso livello e ti forniscono astrazioni indipendenti dalla piattaforma.

Problemi correlati