Маршал Ушорт [] по сети - PullRequest
       31

Маршал Ушорт [] по сети

1 голос
/ 04 ноября 2011

Я создал 2 простые консольные программы и простую структуру.

M11 Объект - это тестовый объект, который мы хотим отправить по сети.

using System.Runtime.InteropServices;
using System;

namespace MessageInfo
{

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct M11
{
    /// <summary>
    /// Message Header
    /// </summary>
    public MessageHeader MessageHeader;

    [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_I2)]
    public short[] ArrayOfNumber;
}

/// <summary>
/// Message Header
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MessageHeader
{
    public byte mType;
    public ulong mId;
}
}

И SimpleSender будет маршалировать объект иотправить по сети.

    static void Main(string[] args)
    {

        int m11Size = 0;
        M11 m11Structure = new M11();

        MessageHeader header = new MessageHeader();
        header.mType = 0x01;
        header.mId = Convert.ToUInt64(DateTime.Now.ToString("yyyyMMddHHmmssfff"));
        m11Size += Marshal.SizeOf(header);

        m11Structure.MessageHeader = header;

        short[] arrayOfNumber = new short[5] { 5, 4, 3, 2, 1 };
        m11Structure.ArrayOfNumber = arrayOfNumber;
        m11Size += Marshal.SizeOf(typeof(ushort)) * arrayOfNumber.Length;            

        byte[] m11Bytes = new byte[m11Size];
        GCHandle m11Handler = GCHandle.Alloc(m11Bytes, GCHandleType.Pinned);
        try
        {
            IntPtr m11Ptr = m11Handler.AddrOfPinnedObject();
            Marshal.StructureToPtr(m11Structure, m11Ptr, false);
            using (Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
            {
                try
                {
                    IPEndPoint iep = new IPEndPoint(IPAddress.Parse("192.168.2.110"), 3000);
                    sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
                    sock.SendTo(m11Bytes, iep);
                }
                finally
                {
                    sock.Close();
                }
            }

        }
        catch (Exception ex) { Console.Write(ex.ToString()); }
        finally { m11Handler.Free(); }

        Console.ReadLine();
    }

Последний, но не по значению, получатель, который получит байты и преобразует их в объект.System.AccessViolationException: попытка чтения или записи защищенной памяти ", когда она вызывает Marshal.PtrToStructure.

Несколько замечаний: 1. Работает нормально только с MessageHeader.2. И массив ushort имеет динамический размер.

Заранее спасибо.

Анри

1 Ответ

0 голосов
/ 04 ноября 2011

Что касается ответа.Вы не можете легко упорядочить массив с динамической длиной.(хотя вы можете использовать SafeArray, см. Marshal safearray struct внутри struct )

Если вы хотите передавать объекты по проводам, то в первую очередь не рекомендуется использовать маршаллинг.Используйте сериализацию для отправки объектов по проводам!Подсказка, посмотрите на protobuf-net от Marc Gravell для очень эффективной библиотеки сериализации.

Ваш код также поврежден.Вы используете UDP, который может быть трудным для начала, так как он не гарантирует порядок и доставку.Вы должны либо определить свой собственный протокол, который позаботится обо всем этом, либо просто полагаться на TCP / IP, который по своей природе обеспечивает механизмы для предотвращения этих проблем.Кроме того, сокеты основаны на потоке, а не на пакетах.Я настоятельно рекомендую вам немного погуглить, как работать с сокетами

...