2010-06-10 61 views
2

我使用UdpClient查询有关服务器名称,地图,玩家数量等分裂UDP数据包

我已经按照此页面上的指引游戏服务器(A2S_INFO) http://developer.valvesoftware.com/wiki/Server_queries#Source_servers

而我得到一个正确的答案:

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

我不知道我怎么会去获取信息的每块(服务器名称,地图等)。

任何帮助?我假设你必须查看我链接的wiki中指定的回复格式,但我不知道该怎么做。

回答

5

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

你是如何得到答复的?

  1. 如果它已经在流中,则设置。
  2. 如果它是在一个字节数组中,首先将它包装在MemoryStream中。我认为UdpClient这样做。

然后,使用该流构造BinaryReader。记住,流和阅读器都需要是Disposed之一。

BinaryReader reader = new BinaryReader(stream); 

现在,您可以拨打读者的方法,如ReadByteReadInt32等来依次读取从响应每个字段,使用对应字段的类型的方法。该流在读取时更新其内部偏移量,因此您可以自动从响应缓冲区的正确位置读取连续的字段。 BinaryReader已经有合适的蒸汽包所使用的五个非字符串类型的方法:

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

string有点棘手,因为BinaryReader还没有方法读取由Valve指定格式的字符串(空终止的UTF-8),所以您必须自己逐字节地执行。为了使它看起来就像任何其他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,而不是手动组装单个字节值。