拆分UDP数据包 [英] Splitting up UDP packet

查看:444
本文介绍了拆分UDP数据包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用UdpClient查询游戏服务器的服务器名称,地图,玩家数量等.

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

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

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

我得到正确的答复:

替代文本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).

有帮助吗?我假设有人必须查看链接的Wiki中指定的回复格式,但是我不知道该怎么做.

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.

推荐答案

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

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.

您如何获得回复?

  1. 如果已经在流中,则设置为您.
  2. 如果在字节数组中,请先将其包装在MemoryStream中.我认为UdpClient就是这样.
  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.

然后,使用流构造一个BinaryReader.请记住,流和阅读器都必须是Disposed.

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

BinaryReader reader = new BinaryReader(stream);

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

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(是的,里面有一个U; Valve页面说这些是未签名的)
  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有点棘手,因为BinaryReader还没有方法读取由Valve(空终止的UTF-8)指定的格式的字符串,因此您必须自己做字节按字节.为了使它看起来尽可能地类似于其他任何BinaryReader方法,您可以编写一个扩展方法(未经测试的代码;这是其要旨):

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.

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

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

这篇关于拆分UDP数据包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆