Структуры в байтовые массивы для отправки через сокеты
-
19-08-2019 - |
Вопрос
Каков наилучший способ получить массив байтов из структуры для отправки через сокеты TCP? Я использую .Net (VB или C #).
Решение
Если вы используете C #, вы также можете самостоятельно упаковать его в собственный буфер, чтобы лучше контролировать сериализацию.
Вам необходимо добавить соответствующий атрибут в вашу структуру,
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack=1)]
Затем вы можете сериализовать его, используя:
/// <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;
}
Другие советы
Вам следует изучить сериализацию . Вам доступно несколько вариантов: Протокол Буферы (реализации пользователями SO первого и второго ранга) для XML для BinaryFormatter .
Если вы хотите позаботиться о порядке байтов (для связи в гетерогенной сети), единственный способ сделать это - поле за полем. Р>
Почему бы просто не использовать двоичный ридер для заполнения полей структуры и снова их считывать? Все, что вам нужно знать, это размер полей в структуре и их положение в потоке, нет необходимости в неуправляемых решениях. Вот пример из waveplayer, который я написал ..
/// <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;
}
Вам нужно быть более конкретным и сообщить нам свой язык.
Для многих языков существуют готовые рамки или даже части стандартной языковой среды для выполнения подобных задач.
Я предполагаю, что язык C, так как вы говорите " struct "
вы можете использовать функцию под названием
ssize_t write (int fd, const void * buf, size_t count);
где FD - файловый дескриптор сокета буфер - это адрес структуры, а count - это размер в байтах
вы бы использовали его как
write (сокет, & amp; struct_var, sizeof (struct_var));