简体   繁体   English

拆分UDP数据包

[英]Splitting up UDP packet

I'm using UdpClient to query game servers about server name, map, number of players, etc. 我正在使用UdpClient来查询游戏服务器的服务器名称,地图,玩家数量等。

I've followed the guidelines on this page (A2S_INFO) http://developer.valvesoftware.com/wiki/Server_queries#Source_servers 我已遵循此页面上的指南(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 替代文字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. 我假设有人必须查看链接的Wiki中指定的回复格式,但是我不知道该怎么做。

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. 您可以使用BinaryReader类的类来读取数据包中的字节组,并将其解释为适当的数据类型。

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. 如果在字节数组中,请先将其包装在MemoryStream I think UdpClient does it this way. 我认为UdpClient就是这样做的。

Then, construct a BinaryReader using the stream. 然后,使用该流构造BinaryReader Remember, both the stream and the reader need to be Disposed of. 记住,流和阅读器都需要Disposed

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. 现在,您可以使用与字段类型相对应的方法来调用读取器的方法,如ReadByteReadInt32等,以从响应中依次读取每个字段。 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: BinaryReader已经具有适用于Steam数据包中使用的五种非字符串类型的方法:

  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) long long: ReadUInt64 (是的,里面有一个U; Valve页面说这些是未签名的)

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. string有点棘手,因为BinaryReader还没有方法以Valve(空终止的UTF-8)指定的格式读取字符串,因此您必须自己逐字节进行操作。 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): 为了使它看起来与其他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());
}

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. 您可以使用类似的代码通过BinaryWriter创建请求数据包,而不是手动组装单个字节值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM