我目前正在为我自己的F1方向盘显示器工作。F1 2019 (由codemasters提供)通过UDP发送数据。该数据存储在字节数组中。
我在解码返回的数组时遇到了一些问题。问题是我得到了很多信息,但我不知道如何处理这些信息。我会告诉你我试过的东西。
我通过端口20777 (游戏的标准端口)连接到游戏:
using System.Net;
using System.Net.Sockets;
var Client = new UdpClient(20777); //Connectionport在下一段代码中,我从游戏中获取信息:
var RemoteIP = new IPEndPoint(IPAddress.Any, 60240);
byte[] received = Client.EndReceive(res, ref RemoteIP);如您所见,游戏中的数据当前存储在一个字节数组中。
(对我来说)最难的部分来了。
F1 2019发送的数据被打包在结构中(从我从他们的网站上了解到的)。但我不知道如何从字节数组中获取信息并进入正确的变量(例如,当前速度是多少,或者汽车的档位是多少)。
有关数据包的信息位于codemasters的网站上:
https://forums.codemasters.com/topic/44592-f1-2019-udp-specification/
现在实际的问题是:
当我键入这行代码时:
short game_version = BitConverter.ToInt16(received, 0);我将其显示在文本框中,变量game_version现在是2019。
我不明白为什么有了indexnumber 0,字节就会在2019年转换。
我不知道用哪个索引号来得到我想要的每个变量。
我希望有人能对这件事有所了解。在codemasters论坛上,似乎每个人都知道如何从字节数组中获取数据。
向您致以亲切的问候。
发布于 2020-02-16 18:06:25
好的,我发现(感谢Jeremy),我需要从字节数组中获取一个结构。我遵循了以下示例:Example1 Example2
因此,Codemaster( F1 2019的制造商)正在发送一个字节数组,其中包含所有需要的信息。它们已将结构转换为字节数组。这些结构包含游戏发出的所有信息。因此,需要做的事情是将字节数组转换回结构。请记住,来自Codemaster的结构布局需要保持不变,否则您将无法在正确的变量中获得正确的信息。
PacketHeader packetheader = ByteArrayToPacketHeader(received);
PacketHeader ByteArrayToPacketHeader(byte[] bytes)
{
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
PacketHeader stuff;
try
{
stuff = (PacketHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PacketHeader));
}
finally
{
handle.Free();
}
return stuff;
}目前,上面的代码将传入的字节数组(已接收)转换为结构PacketHeader。该结构如下所示:
public struct PacketHeader
{
public ushort m_packetFormat; // 2019
public byte m_gameMajorVersion; // Game major version - "X.00"
public byte m_gameMinorVersion; // Game minor version - "1.XX"
public byte m_packetVersion; // Version of this packet type, all start from 1
public byte m_packetId; // Identifier for the packet type, see below
public ulong m_sessionUID; // Unique identifier for the session
public float m_sessionTime; // Session timestamp
public uint m_frameIdentifier; // Identifier for the frame the data was retrieved on
public byte m_playerCarIndex; // Index of player's car in the array
};每个包含信息的包(结构)都有一个PacketHeader。通过转换每个包的报头,您可以在变量: stuff中获得相应的信息。
Here you can see the information of the PacketHeader while debugging
我将尝试解释代码的作用。我不确定我能不能100%地解释它,因为我自己并不完全理解它。
PacketHeader ByteArrayToPacketHeader(byte[] bytes)
{
}首先,我做了一个新的方法。此方法将结构从字节数组中拉出。然后,我将所需的变量添加到方法中:
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
PacketHeader stuff;我真的不理解句柄,但如果它是我想的那样,它就会锁定字节,这样它们就可以正确转换。
我还创建了一个变量: stuff。在这个变量中,结构将被“存储”。在下一部分中,我添加了转换代码:
try
{
stuff = (PacketHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PacketHeader));
}
finally
{
handle.Free();
}
return stuff;转换就是这段代码。在代码中填充PacketHeader时,将遵循结构布局并填充变量。
需要完成的最后一部分是调用此方法。我是这样做的:
PacketHeader packetheader = ByteArrayToPacketHeader(received);在这里,您可以看到我调用了方法packetheader并创建了一个名为PacketHeader的变量。在这个变量中,所有信息都将被存储。
重要!填写要在接收到的插槽中使用的字节数组。这样,该方法将使用该字节数组。
如果我现在想从PacketHeader结构中调用一个变量,我只需编写以下代码:
packetheader.m_packetFormat (example)目前,我能够从PacketHeader中获得正确的信息,但仍然不能从其他结构中获得。但我离完成我的项目又近了一步!
如果解释不完全正确,我很抱歉。(我自己还在学习)。如果您对此解释有任何建议或注意事项,请与我联系。我想了解更多关于这个主题的知识。
致以亲切的问候。
https://stackoverflow.com/questions/60231960
复制相似问题