分割UDP数据包

发布于 2024-09-05 07:32:38 字数 509 浏览 5 评论 0原文

我正在使用 UdpClient 查询游戏服务器有关服务器名称、地图、玩家数量等的信息。

我已遵循此页面上的指南 (A2S_INFO) http://developer.valvesoftware.com/wiki/Server_queries#Source_servers

和我'我得到了正确的回复:

替代文本http://data.fuskbugg.se/skalman01/reply。 JPG

我不知道如何获取每块信息(服务器名称、地图等)。

有什么帮助吗?我假设人们必须查看我链接的维基中指定的回复格式,但我不知道如何理解它。

I'm using UdpClient to query game servers about server name, map, number of players, etc.

I've followed the guidelines on this page (A2S_INFO)
http://developer.valvesoftware.com/wiki/Server_queries#Source_servers

and I'm getting a correct reply:

alt text http://data.fuskbugg.se/skalman01/reply.JPG

I have no idea how I would go about to get each chunk of information (server name, map and the like).

Any help? I'm assuming one would have to look at the reply format specified in the wiki I linked, but I don't know what to make of it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

春夜浅 2024-09-12 07:32:38

回复格式为您提供回复数据包中字段的顺序和类型,基本上就像一个结构体。您可以使用像 BinaryReader 这样的类来读取数据包中的字节组并将它们解释为适当的数据类型。

你如何得到回应?

  1. 如果它已经在流中,那么您就已经设置好了。
  2. 如果它位于字节数组中,请先将其包装在 MemoryStream 中。我认为 UdpClient 就是这样做的。

然后,使用该流构造一个 BinaryReader。请记住,流和读取器都需要Dispose

BinaryReader reader = new BinaryReader(stream);

您现在可以调用读取器的方法,例如 ReadByteReadInt32 等,使用与字段类型相对应的方法从响应中依次读取每个字段。流在读取时更新其内部偏移量,因此您可以自动从响应缓冲区中的正确位置读取连续的字段。 BinaryReader 已经具有适合 Steam 数据包中使用的五种非字符串类型的方法:

  1. byte: ReadByte
  2. short: ReadInt16
  3. long: ReadInt32
  4. float: ReadSingle
  5. long long: ReadUInt64 (是的,里面有一个 U;Valve 页面说这些是无符号的)

string 有点棘手,因为 BinaryReader 还没有读取 Valve 指定格式的字符串(以 null 结尾的 UTF-8)的方法,所以你必须自己做,byte按字节。为了使其看起来尽可能像任何其他 BinaryReader 方法,您可以编写一个扩展方法(未经测试的代码;这是它的要点):

public static string ReadSteamString(this BinaryReader reader)
{
  // To hold the list of bytes making up the string
  List<byte> str = new List<byte>();
  byte nextByte = reader.ReadByte();
  // Read up to and including the null terminator...
  while (nextByte != 0)
  {
    // ...but don't include it in the string
    str.Add(nextByte);
    nextByte = reader.ReadByte();
  }

  // Interpret the result as a UTF-8 sequence      
  return Encoding.UTF8.GetString(str.ToArray());
}

一些示例用法,以及您提供的响应数据包:

// Returns -1, corresponding to FF FF FF FF
int header = reader.ReadInt32();
// Returns 0x49, for packet type
byte packetType = reader.ReadByte();
// Returns 15, for version
byte ver = reader.ReadByte();
// Returns "Lokalen TF2 #03 All maps | Vanilla"
string serverName = reader.ReadSteamString();
// Returns "cp_well"
string mapName = reader.ReadSteamString();
// etc.

您可以使用类似的代码来创建请求数据包,使用 BinaryWriter 而不是手动组装各个字节值。

The reply format gives you the order and type of fields in the reply packet, basically like a struct. You can use a class like BinaryReader to read groups of bytes in the packet and interpret them as the appropriate data types.

How are you getting the response?

  1. If it's in a stream already, you're set.
  2. If it's in a byte array, wrap it in a MemoryStream first. I think UdpClient does it this way.

Then, construct a BinaryReader using the stream. Remember, both the stream and the reader need to be Disposed of.

BinaryReader reader = new BinaryReader(stream);

You can now call the reader's methods like ReadByte, ReadInt32 etc. to read each field in turn from the response, using methods corresponding to the fields' types. The stream updates its internal offset as it's read, so you automatically read successive fields from the right place in the response buffer. BinaryReader already has methods appropriate to the five non-string types used in the Steam packets:

  1. byte: ReadByte
  2. short: ReadInt16
  3. long: ReadInt32
  4. float: ReadSingle
  5. long long: ReadUInt64 (yes, there's a U in there; the Valve page says these are unsigned)

string is a bit trickier, because BinaryReader doesn't already have methods to read strings in the format specified by Valve (null-terminated UTF-8), so you'll have to do it yourself, byte by byte. To make it look as much like any other BinaryReader method as possible, you could write an extension method (untested code; this is the gist of it):

public static string ReadSteamString(this BinaryReader reader)
{
  // To hold the list of bytes making up the string
  List<byte> str = new List<byte>();
  byte nextByte = reader.ReadByte();
  // Read up to and including the null terminator...
  while (nextByte != 0)
  {
    // ...but don't include it in the string
    str.Add(nextByte);
    nextByte = reader.ReadByte();
  }

  // Interpret the result as a UTF-8 sequence      
  return Encoding.UTF8.GetString(str.ToArray());
}

Some example usage, with the response packet you gave:

// Returns -1, corresponding to FF FF FF FF
int header = reader.ReadInt32();
// Returns 0x49, for packet type
byte packetType = reader.ReadByte();
// Returns 15, for version
byte ver = reader.ReadByte();
// Returns "Lokalen TF2 #03 All maps | Vanilla"
string serverName = reader.ReadSteamString();
// Returns "cp_well"
string mapName = reader.ReadSteamString();
// etc.

You can use similar code for creating your request packets, using a BinaryWriter instead of manually assembling individual byte values.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文