2

構造体からバイト配列を取得してTCPソケットを介して送信するための最良の方法は何ですか?.Net(VBまたはC#)を使用しています。

4

6 に答える 6

8

memcpy1 つのオプションは、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;
    }

それでも、これは移植性の最も低いソリューションです。両側で同じ配置とエンディアンを使用する必要があり、構造体自体を変更する必要がある場合は、バージョン管理を自分で実装する必要があります。

ほとんどの場合、シリアル化形式は内部データ構造の直接コピーであってはなりません。

于 2009-03-16T15:22:28.733 に答える
3

Serializationを調べる必要があります。Protocol Buffers (1 位と 2 位の SO ユーザーによる実装) からXmlBinaryFormatterまで、多数のオプションを利用できます。

于 2009-03-16T15:18:25.700 に答える
2

バイナリ リーダーを使用して構造体のフィールドにデータを入力し、それらを再度読み込んでみませんか? 知っておく必要があるのは、構造体のフィールドのサイズとストリーム内の位置だけです。アンマネージド ソリューションは必要ありません。これは、私が書いた 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;
    }
于 2013-10-14T17:07:54.190 に答える
1

エンディアンの面倒を見る(異種ネットワークで通信する)場合、これを行う唯一の方法はフィールドごとです。

于 2009-03-16T15:10:10.180 に答える
0

より具体的に、言語を教えてください。

多くの言語には、これらの種類のことを行うための既製のフレームワーク、または言語の標準環境の一部があります。

于 2009-03-16T15:09:34.880 に答える
0

あなたが「構造体」と言うので、私はC言語を想定しています

と呼ばれる関数を使用できます

ssize_t write(int fd、const void * buf、size_t count);

ここで、FDはソケットのファイル記述子であり、バッファは構造体のアドレスであり、countはバイト単位のサイズです。

あなたはそれを次のように使うでしょう:

write(socket、&struct_var、sizeof(struct_var));

于 2009-03-16T15:11:20.990 に答える