回复格式为您提供了回复数据包中的字段顺序和类型,基本上就像一个结构。您可以使用类如BinaryReader
来读取数据包中的字节组,并将它们解释为适当的数据类型。
你是如何得到答复的?
- 如果它已经在流中,则设置。
- 如果它是在一个字节数组中,首先将它包装在
MemoryStream
中。我认为UdpClient
这样做。
然后,使用该流构造BinaryReader
。记住,流和阅读器都需要是Disposed
之一。
BinaryReader reader = new BinaryReader(stream);
现在,您可以拨打读者的方法,如ReadByte
,ReadInt32
等来依次读取从响应每个字段,使用对应字段的类型的方法。该流在读取时更新其内部偏移量,因此您可以自动从响应缓冲区的正确位置读取连续的字段。 BinaryReader
已经有合适的蒸汽包所使用的五个非字符串类型的方法:
byte: ReadByte
short: ReadInt16
long: ReadInt32
float: ReadSingle
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
,而不是手动组装单个字节值。