Domanda

Io sono l'invio e la ricezione di dati binari in/da un dispositivo in pacchetti da 64 byte).I dati sono di un formato specifico, le parti di cui variare a seconda del tipo di richiesta / risposta.

Ora sto progettando un interprete per i dati ricevuti.La semplice lettura di dati da posizioni è OK, ma non sembra che fresco quando ho una dozzina di diversi formati di risposta.Attualmente sto pensando di creare un paio di strutture per quello scopo, ma non so come andare con imbottitura.

Forse c'è un modo migliore?


Related:

È stato utile?

Soluzione

Ho fatto innumerevoli volte:è uno scenario molto comune.Ci sono un certo numero di cose che ho praticamente sempre.

Non preoccuparti troppo di rendere più efficiente cosa disponibile.

Se facciamo vento a spendere un sacco di tempo di imballaggio e disimballaggio dei pacchetti, poi si può sempre cambiare per essere più efficiente.Mentre non ho incontrato un caso in cui ho dovuto ancora, io non sono stato di attuazione dei router di rete!

Durante l'utilizzo di strutture/sindacati è l'approccio più efficiente in termini di runtime, è dotato di una serie di complicazioni:convincente il compilatore per confezionare le strutture/sindacati per abbinare l'ottetto struttura dei pacchetti di cui hai bisogno, lavorare per evitare l'allineamento e le modalita ' di problemi, e la mancanza di sicurezza, poiché non vi è poca o nessuna possibilità di fare controlli di integrità sulla build di debug.

Mi capita spesso di vento fino con un'architettura tra cui le seguenti cose:

  • Un pacchetto di base di classe.Comune di campi di dati sono accessibili (ma non modificabile).Se i dati non sono memorizzati in un formato compresso, quindi c'è una funzione virtuale che produrrà un ricco pacchetto.
  • Un numero di presentazione delle classi per specifici tipi di pacchetti, derivata dal comune tipo di pacchetto.Se stiamo usando una funzione di imballaggio, quindi ogni presentazione di classe deve implementare.
  • Tutto ciò che può essere dedotto dal tipo specifico di presentazione della classe (es.un tipo di pacchetto id da un campo di dati comune), è trattata come parte di inizializzazione e in caso contrario è immodificabile.
  • Ogni presentazione di classe può essere costruito da un scompattato il pacchetto, o con garbo di non riuscire se i dati a pacchetto non valido per il tipo.Questo può poi essere avvolto in una fabbrica per la vostra convenienza.
  • Se non abbiamo RTTI disponibili, siamo in grado di ottenere "povero uomo RTTI" utilizzando l'id del pacchetto per determinare quale di presentazione della classe di un oggetto davvero.

In tutto questo, è possibile (anche se solo per le versioni di debug) per verificare che ogni campo è modificabile è stato impostato un buon valore.Mentre potrebbe sembrare un sacco di lavoro, rende molto difficile avere un invalidamente formattato pacchetto pre-confezionato pacchetti contenuti possono essere easilly controllata da occhio utilizzo di un debugger (dal momento che è tutto normale piattaforma-formato nativo variabili).

Se dobbiamo attuare una più efficace schema di archiviazione, che può essere avvolto in questa astrazione di poco le prestazioni di costo.

Altri suggerimenti

È necessario utilizzare le strutture e o unioni. Avrai bisogno di assicurarsi che i dati sia correttamente imballato su entrambi i lati della connessione e si consiglia di tradurre da e verso l'ordine dei byte di rete su ciascuna estremità se c'è qualche possibilità che entrambi i lati della connessione potrebbe essere in esecuzione con un diverso endianess.

Per fare un esempio:

#pragma pack(push)  /* push current alignment to stack */
#pragma pack(1)     /* set alignment to 1 byte boundary */
typedef struct {
    unsigned int    packetID;  // identifies packet in one direction
    unsigned int    data_length;
    char            receipt_flag;  // indicates to ack packet or keep sending packet till acked
    char            data[]; // this is typically ascii string data w/ \n terminated fields but could also be binary
} tPacketBuffer ;
#pragma pack(pop)   /* restore original alignment from stack */

e poi quando si assegna:

packetBuffer.packetID = htonl(123456);

e poi quando si riceve:

packetBuffer.packetID = ntohl(packetBuffer.packetID);

Qui ci sono alcune discussioni su Endianness e Allineamento e struttura Imballaggio

Se non imballare la struttura si finirà per allineato ai contorni di parole e il layout interno della struttura e la sua dimensione non sarà corretto.

E 'difficile dire quale sia la soluzione migliore è senza conoscere il formato esatto (s) dei dati. Hai pensato di usare i sindacati?

Sono d'accordo con Wuggy. È inoltre possibile utilizzare la generazione di codice per fare questo. Utilizzare un semplice file di definizione di dati per definire tutti i tipi di pacchetti, quindi eseguire uno script Python su di esso per generare strutture prototipo e serialiation funzioni / deserializzazione per ciascuno di essi.

Questa è una soluzione "out-of-the-box", ma io suggerirei di dare un'occhiata al Python costruire biblioteca.

  

Construct è una libreria Python per   l'analisi e la costruzione dei dati   strutture (binari o testuali). È   basata sul concetto di dati che definiscono   strutture in maniera dichiarativa,   piuttosto che codice procedurale: più   costrutti complessi sono composti da un   gerarchia dei più semplici. È il   prima biblioteca che rende divertente l'analisi,   invece del solito mal di testa è   oggi.

costrutto è molto robusto e potente, e solo leggendo il tutorial vi aiuterà a capire meglio il problema. L'autore ha anche piani per auto-generazione di codice C da definizioni, quindi è sicuramente vale la pena di leggere.

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