Domanda

Questa è una specie di un ramo della mia altra domanda . Leggetelo se ti piace, ma non è necessario.

Fondamentalmente, ho capito che per utilizzare in modo efficace C # s 'BeginReceive () su messaggi di grandi dimensioni, devo (a) leggere la lunghezza del pacchetto prima, quindi leggere esattamente quel numero di byte o (b) utilizzare un fine-di- delimitatore pacchetto. La mia domanda è: sono uno di questi presenti nel buffer di protocollo? Non li ho ancora utilizzato, ma andare oltre la documentazione non sembra che ci sia un colpo di testa lunghezza o un delimitatore.

In caso contrario, che cosa devo fare? Devo solo costruire il messaggio poi prefisso / suffisso con il / delimitatore di intestazione lunghezza EOP?

È stato utile?

Soluzione

È necessario includere la dimensione o la segnaletica situata all'estremità nel protocollo. Nulla è costruito in prese basate stream (TCP / IP) diversi da supportare un flusso indefinito di ottetti arbitrariamente suddiviso in pacchetti separati (e pacchetti può essere versato in transito pure).

Un approccio semplice sarebbe per ogni "messaggio" di avere un colpo di testa dimensione fissa, includere sia una versione di protocollo e una dimensione del carico utile e tutti gli altri dati fissi. Poi il contenuto del messaggio (payload).

, un messaggio piè di pagina (dimensioni fisse) potrebbe essere aggiunto con un checksum o anche una firma crittografica (a seconda delle esigenze di sicurezza / affidabilità).

Conoscere la dimensione del payload consente di mantenere la lettura di un numero di byte che sarà abbastanza per il resto del messaggio (e se una lettura completa con meno, fare un altro di lettura per i byte rimanenti fino a quando è stato ricevuto l'intero messaggio) .

Avere un indicatore di messaggio di fine funziona anche, ma è necessario definire come gestire il vostro messaggio contenente quella sequenza stessa ottetto ...

Altri suggerimenti

Ci scusiamo per arrivare in ritardo alla festa. Io sono l'autore di protobuf-net, una delle implementazioni C #. Per l'utilizzo della rete, si dovrebbe prendere in considerazione i metodi "[de] SerializeWithLengthPrefix" - in questo modo, esso gestirà automaticamente le lunghezze per voi. Ci sono esempi nel sorgente.

Non voglio entrare nei dettagli enorme su un vecchio post, ma se volete sapere di più, aggiungere un commento e io tornare a voi.

Sono d'accordo con Matt che un colpo di testa è meglio di un piè di pagina per il buffer protocollo, per il motivo principale che, come PB è un protocollo binario è problematico a venire con un piè di pagina che non sarebbe anche una sequenza di messaggio valido. Un sacco di protocolli footer-based (tipicamente quelli EOL) funziona perché il contenuto del messaggio è in un intervallo definito. (Tipicamente 0x20 - 0x7F ASCII)

Un approccio utile è di avere il codice di livello più basso appena letto buffer fuori della presa e presentarle fino a un livello di inquadramento che assembla i messaggi completi e ricorda quelli parziali (vi presento un approccio asincrono a questo (utilizzando il CCR) < a href = "http://iodyner.spaces.live.com/blog/cns!7B505254340D5E9A!180.entry" rel = "nofollow noreferrer"> qui , anche se per un protocollo di linea).

Per coerenza, si può sempre definire il tuo messaggio come un messaggio PB con tre campi: a-int fisso come la lunghezza, un enum come il tipo, e una sequenza di byte che contiene i dati effettivi. Ciò mantiene l'intero protocollo di rete trasparente.

TCP / IP, così come UDP, i pacchetti comprendono qualche riferimento alla loro dimensione. Il IP intestazione contiene un campo a 16 bit che specifica la lunghezza dell'intestazione IP e di dati in byte. contiene un campo di 4 bit che specifica la dimensione dell'intestazione TCP in 32- parole bit. UDP intestazione contiene un campo a 16 bit che specifica la lunghezza dell'intestazione UDP e di dati in byte.

Ecco la cosa.

Utilizzando le prese standard run-of-the-mill in Windows, se si sta utilizzando lo spazio dei nomi System.Net.Sockets in C # o la roba Winsock nativo in Win32, non si vede mai i / TCP / UDP header IP. Queste intestazioni vengono eliminati in modo che quello che si ottiene quando si legge il socket è il carico utile attuale, vale a dire, i dati che è stato inviato.

Lo schema tipico da tutto ciò che abbia mai visto e fatto usando i socket è che si definisce un'intestazione a livello di applicazione che precede i dati che si desidera inviare. Come minimo, questa intestazione dovrebbe includere la dimensione dei dati da seguire. Questo vi permetterà di leggere ogni "messaggio" nella sua interezza, senza dover indovinare come alle sue dimensioni. È possibile ottenere sofisticato come si vuole con esso, ad esempio, i modelli di sync, CRC, la versione, il tipo di messaggio, ecc, ma la dimensione del "messaggio" è tutto ciò che davvero necessità.

E per quello che vale, io suggerirei di usare un colpo di testa invece di un delimitatore di fine pacchetto. Non sono sicuro se c'è uno svantaggio signficant per il delimitatore EOP, ma il colpo di testa è l'approccio utilizzato dalla maggior parte dei protocolli IP che ho visto. Inoltre, sembra solo più intuitivo per me di elaborare un messaggio fin dall'inizio, piuttosto che aspettare per un certo modello di apparire nel mio flusso per indicare che il mio messaggio è completo.

EDIT: ho appena venuto a conoscenza del progetto di Google buffer protocollo. Da quello che posso dire, è uno schema binario di serializzazione / deserializzazione per WCF (sono sicuro che sia una grossolana). Se si utilizza WCF, non c'è bisogno di preoccuparsi per le dimensioni dei messaggi inviati, perché l'impianto idraulico WCF si prende cura di questo dietro le quinte, che è probabilmente il motivo per cui non hai trovato nulla legati alla lunghezza del messaggio nel protocollo documentazione di buffer. Tuttavia, nel caso di prese, conoscendo la dimensione aiuterà tremendamente come discusso sopra. La mia ipotesi è che si serializzare i dati utilizzando i buffer di protocollo e quindi virare su qualunque intestazione applicazione si arriva con prima di inviarlo. Sul lato ricezione, si tira fuori l'intestazione e poi de-serializzare il resto del messaggio.

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