[英]Marshal ushort[] over network
我創建了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();
}
最后但並非最不重要的一點是,接收器將接收字節並轉換為對象。
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數組具有動態大小。
提前致謝。
亨利
至於答案。 您不能輕易地封送動態長度的數組。 (盡管您可以使用SafeArray,但請參閱struct內部的Marshal結構的safearray )
如果要通過導線傳輸對象,則不建議首先使用編組。 使用序列化通過電線發送對象! 提示,請看Marc Gravell的protobuf-net,它提供了一個非常有效的序列化庫。
您的代碼也有問題。 開始使用UDP可能會很麻煩,因為它不能保證順序和可交付性。 您要么必須定義自己的協議來處理所有這些問題,要么僅依賴於TCP / IP,后者固有地提供了防止這些問題的機制。 緊接着,套接字是基於流的,而不是基於分組的。 我真的鼓勵您對如何使用套接字進行一些谷歌搜索
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.