首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过网络封送ushort[]

通过网络封送ushort[]
EN

Stack Overflow用户
提问于 2011-11-04 16:41:15
回答 1查看 699关注 0票数 1

我创建了2个简单的控制台程序和一个简单的结构。

M11对象是我们想要通过网络发送的测试对象。

代码语言:javascript
复制
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将编组该对象并通过网络发送。

代码语言:javascript
复制
    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();
    }

最后但并非最不重要的是,接收方将接收字节并转换为对象。

代码语言:javascript
复制
    static void Main(string[] args)
    {
        M11 m11Structure = new M11();
        using (UdpClient udpClient = new UdpClient(3000))
        {                
            try
            {
                IPEndPoint ep = new IPEndPoint(IPAddress.Parse("192.168.2.110"), 3000);
                byte[] m11Bytes = udpClient.Receive(ref ep);
                GCHandle m11Handler = GCHandle.Alloc(m11Bytes, GCHandleType.Pinned);
                try
                {
                    IntPtr m11Ptr = m11Handler.AddrOfPinnedObject();
                    m11Structure = (M11)Marshal.PtrToStructure(m11Ptr, typeof(M11));
                    PrintM11Structure(m11Structure);
                }
                catch (Exception ex) { Console.WriteLine(ex.ToString()); }
                finally { m11Handler.Free(); }

            }
            finally { udpClient.Close(); }
        }

        Console.ReadLine();
    }

问题是,当接收器程序调用Marshal.PtrToStructure时,它总是抛出"System.AccessViolationException:尝试读取或写入受保护的内存“。

需要注意的几件事: 1.它只适用于MessageHeader。2. ushort数组具有动态大小。

提前谢谢。

亨利

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-11-04 17:14:46

至于答案。您不能轻易地封送具有动态长度的数组。(尽管您可以使用SafeArray,但请参阅Marshal safearray of struct inside struct )

如果你想通过网络传输对象,那么首先不推荐使用编组。使用序列化通过网络发送对象!提示,看看Marc Gravell的protobuf-net,它是一个非常高效的序列化库。

你的代码也有问题。您使用UDP,这可能是一个痛苦的开始,因为它不能保证订单和交付。您要么必须定义自己的协议来处理所有这些问题,要么简单地依赖于TCP/IP,因为TCP/IP本身就提供了防止这些问题的机制。其次,套接字是基于流的,而不是基于包的。我真的鼓励您在谷歌上搜索一下如何使用套接字

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8006701

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档