Estruturas para Byte Arrays para enviar mais soquetes
-
19-08-2019 - |
Pergunta
Qual é a melhor maneira de obter um array de bytes de um struct para enviar mais sockets TCP? Estou usando .Net (VB ou C #).
Solução
Se você estiver usando C #, você também pode empacotá-lo para um buffer nativo si mesmo, para ter melhor controle sobre a serialização.
Você precisa adicionar o atributo apropriado para o seu struct,
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack=1)]
Em seguida, você pode serializar-lo 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;
}
Outras dicas
Você deve olhar para serialização . Há um número de opções disponíveis para você, a partir Protocolo Tampões (implementações de 1º e 2º classificados tão usuários) para Xml para o BinaryFormatter .
Se você estiver disposto a cuidar do endian (para se comunicar em uma rede heterogênea), a única maneira de fazer isso é campo a campo.
Porque não basta usar um leitor de binário para preencher os campos da struct, e lê-los novamente? Tudo que você precisa saber é o tamanho dos campos na struct e da posição no fluxo, não há necessidade de soluções não gerenciados .. Aqui está um exemplo de um waveplayer eu escrevi ..
/// <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;
}
Você precisa ser mais específico e diga-nos o seu idioma.
Para muitas línguas, existem estruturas prontas, ou mesmo partes do ambiente padrão da linguagem, para fazer esses tipos de coisas.
Estou assumindo a linguagem C, uma vez que você diz "struct"
Você pode usar uma função chamada
gravar ssize_t (int fd, const void * buf, size_t contagem);
onde FD é o FileDescriptor do soquete o tampão é o endereço da estrutura, e a contagem é o tamanho em bytes
você iria usá-lo como:
write (soquete, & struct_var, sizeof (struct_var));