更新:这个问题的答案帮助我编写了开源项目 AlicanC's Modern Warfare 2 Tool on GitHub .您可以在 MW2Packets.cs 中看到我如何读取这些数据包以及我编码的扩展以读取 Extensions.cs 中的大端数据.
我正在捕获 Call of Duty: Modern Warfare 2 的 UDP 数据包使用 Pcap.Net在我的 C# 应用程序中。我从图书馆收到了一个 byte[]
。我尝试将其像字符串一样进行解析,但效果不佳。
我的 byte[]
有一个通用数据包 header ,然后是另一个特定于数据包类型的 header ,然后是大厅中每个玩家的信息。
一位乐于助人的人为我检查了一些数据包并提出了这些结构:
// Fields are big endian unless specified otherwise.
struct packet_header
{
uint16_t magic;
uint16_t packet_size;
uint32_t unknown1;
uint32_t unknown2;
uint32_t unknown3;
uint32_t unknown4;
uint16_t unknown5;
uint16_t unknown6;
uint32_t unknown7;
uint32_t unknown8;
cstring_t packet_type; // \0 terminated string
};
// Fields are little endian unless specified otherwise.
struct header_partystate //Header for the "partystate" packet type
{
uint32_t unknown1;
uint8_t unknown2;
uint8_t player_entry_count;
uint32_t unknown4;
uint32_t unknown5;
uint32_t unknown6;
uint32_t unknown7;
uint8_t unknown8;
uint32_t unknown9;
uint16_t unknown10;
uint8_t unknown11;
uint8_t unknown12[9];
uint32_t unknown13;
uint32_t unknown14;
uint16_t unknown15;
uint16_t unknown16;
uint32_t unknown17[10];
uint32_t unknown18;
uint32_t unknown19;
uint8_t unknown20;
uint32_t unknown21;
uint32_t unknown22;
uint32_t unknown23;
};
// Fields are little endian unless specified otherwise.
struct player_entry
{
uint8_t player_id;
// The following fields may not actually exist in the data if it's an empty entry.
uint8_t unknown1[3];
cstring_t player_name;
uint32_t unknown2;
uint64_t steam_id;
uint32_t internal_ip;
uint32_t external_ip;
uint16_t unknown3;
uint16_t unknown4;
uint32_t unknown5;
uint32_t unknown6;
uint32_t unknown7;
uint32_t unknown8;
uint32_t unknown9;
uint32_t unknown10;
uint32_t unknown11;
uint32_t unknown12;
uint16_t unknown13;
uint8_t unknown14[???]; // Appears to be a bit mask, sometimes the length is zero, sometimes it's one. (First entry is always zero?)
uint8_t unknown15;
uint32_t unknown16;
uint16_t unknown17;
uint8_t unknown18[???]; // Most of the time this is 4 bytes, other times it is 3 bytes.
};
我在我的 C# 应用程序中重新创建了包头结构,如下所示:
[StructLayout(LayoutKind.Sequential, Pack=1)]
struct PacketHeader
{
public UInt16 magic;
public UInt16 packetSize;
public UInt32 unknown1;
public UInt32 unknown2;
public UInt32 unknown3;
public UInt32 unknown4;
public UInt16 unknown5;
public UInt16 unknown6;
public UInt32 unknown7;
public UInt32 unknown8;
public String packetType;
}
然后我尝试为“partystate” header 制作一个结构,但我收到错误提示 fixed
keyword is unsafe:
[StructLayout(LayoutKind.Sequential, Pack=1)]
struct PartyStateHeader
{
UInt32 unknown1;
Byte unknown2;
Byte playerEntryCount;
UInt32 unknown4;
UInt32 unknown5;
UInt32 unknown6;
UInt32 unknown7;
Byte unknown8;
UInt32 unknown9;
UInt16 unknown10;
Byte unknown11;
fixed Byte unknown12[9];
UInt32 unknown13;
UInt32 unknown14;
UInt16 unknown15;
UInt16 unknown16;
fixed UInt32 unknown17[10];
UInt32 unknown18;
UInt32 unknown19;
Byte unknown20;
UInt32 unknown21;
UInt32 unknown22;
UInt32 unknown23;
}
由于 unknown14
和 unknown18
的大小不同,我无法为播放器条目做任何事情。 (玩家条目是最重要的。)
现在,不知何故,我必须将我必须的 byte[]
转换为这些 PacketHeader
结构。遗憾的是,这并不像 (PacketHeader)bytes
那样简单。我尝试了我在互联网上找到的这种方法,但它引发了 AccessViolationException
:
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
PacketHeader packetHeader = (PacketHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PacketHeader));
我怎样才能做到这一点?
最佳答案
//我在以下位置找到了这个:http://code.cheesydesign.com/?p=572 (我还没有测试过,但是 //乍一看它会工作得很好。)
/// <summary>
/// Reads in a block from a file and converts it to the struct
/// type specified by the template parameter
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="reader"></param>
/// <returns></returns>
private static T FromBinaryReader<T>(BinaryReader reader)
{
// Read in a byte array
byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
// Pin the managed memory while, copy it out the data, then unpin it
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
handle.Free();
return theStructure;
}
关于c# - 将字节数组转换为托管结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6335153/