Struct to Byte Arrays per l'invio su socket
-
19-08-2019 - |
Domanda
Qual è il modo migliore per ottenere un array di byte da una struttura per inviare su socket TCP? Sto usando .Net (VB o C #).
Soluzione
Se stai usando C #, puoi anche eseguirne il marshalling su un buffer nativo, per avere un migliore controllo sulla serializzazione.
Dovresti aggiungere l'attributo appropriato alla tua struttura,
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack=1)]
Quindi puoi serializzarlo usando:
/// <summary>
/// Serializes the specified object into a byte array.
/// </summary>
/// <param name="nativeObject">The object to serialize.</param>
/// <returns></returns>
public static byte[] Serialize(object obj)
{
Type objectType = obj.GetType();
int objectSize = Marshal.SizeOf(obj);
IntPtr buffer = Marshal.AllocHGlobal(objectSize);
Marshal.StructureToPtr(obj, buffer, false);
byte[] array = new byte[objectSize];
Marshal.Copy(buffer, array , 0, objectSize);
Marshal.FreeHGlobal(buffer);
return array;
}
Altri suggerimenti
Dovresti cercare Serializzazione . Sono disponibili numerose opzioni, da Protocollo Buffers (implementazioni da parte degli utenti SO 1 ° e 2 ° classificato) a Xml nel BinaryFormatter .
Se sei disposto a prenderti cura dell'endiano (per comunicare in una rete eterogenea), l'unico modo per farlo è campo per campo.
Perché non usare semplicemente un lettore binario per popolare i campi della struttura e leggerli di nuovo? Tutto quello che devi sapere è la dimensione dei campi nella struttura e la sua posizione nel flusso, senza necessità di soluzioni non gestite. Ecco un esempio di un giocatore di onde che ho scritto ..
/// <summary>Copies header to a stream</summary>
/// <param name="waveData">Wav data stream</param>
/// <param name="format">WAVEFORMATEX wav format</param>
/// <returns>Stream</returns>
public Stream CreateStream(Stream waveData, WAVEFORMATEX format)
{
MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(System.Text.Encoding.ASCII.GetBytes("RIFF".ToCharArray()));
writer.Write((Int32)(waveData.Length + 36)); //File length minus first 8 bytes of RIFF description
writer.Write(System.Text.Encoding.ASCII.GetBytes("WAVEfmt ".ToCharArray()));
writer.Write((Int32)16); //length of following chunk: 16
writer.Write((Int16)format.wFormatTag);
writer.Write((Int16)format.nChannels);
writer.Write((Int32)format.nSamplesPerSec);
writer.Write((Int32)format.nAvgBytesPerSec);
writer.Write((Int16)format.nBlockAlign);
writer.Write((Int16)format.wBitsPerSample);
writer.Write(System.Text.Encoding.ASCII.GetBytes("data".ToCharArray()));
writer.Write((Int32)waveData.Length);
waveData.Seek(0, SeekOrigin.Begin);
byte[] b = new byte[waveData.Length];
waveData.Read(b, 0, (int)waveData.Length);
writer.Write(b);
writer.Seek(0, SeekOrigin.Begin);
return stream;
}
Devi essere più specifico e dirci la tua lingua.
Per molte lingue, ci sono framework già pronti, o anche parti dell'ambiente standard della lingua, per fare questo tipo di cose.
Sto assumendo il linguaggio C poiché dici " struct "
puoi usare una funzione chiamata
ssize_t write (int fd, const void * buf, size_t count);
dove FD è il filedescriptor di socket il buffer è l'indirizzo della struttura e count è la dimensione in byte
lo useresti come:
write (socket, & amp; struct_var, sizeof (struct_var));