应该如何构建真正的数据包?

时间:2016-05-17 23:47:17

标签: c# sockets network-programming

这个问题可能会激怒所有堆栈溢出的神,但我无法理解数据包应该是什么样子。

我指的是如何根据这些指南制作数据包?

sample packet

byte[] data0 = Encoding.Unicode.GetBytes("1");
byte[] data1 = Encoding.Unicode.GetBytes(0x03);
string data2 = "127.0.0.0:80";
string data3 = "";

我想像这样的一切,并从中做出一个字节列表/数组? 或者该字符串必须转换为byte,然后将其打包为 array / list

或许某人有一个简单的解释如何完成?

1 个答案:

答案 0 :(得分:0)

您似乎正在尝试实施客户端以使用Valve的"Master Server Query Protocol"。如果单击"String Zero"链接,您会发现它只是描述了一个以空字符结尾的字符串。据推测,编码是ASCII,但我没有在文档中看到任何明确的内容。

您需要构建一个数据报,其格式如文档中所述。对于ASCII字符,您只需将char转换为int;对于非ASCII字符,您将获得超出ASCII有效范围的值,但char使用UTF16,对于与ASCII共享的字符范围,它也共享实际的字符。然后,您可以将该字符强制转换为byte以用于数据报。但是,这个特定的例子中没有一个真正重要,因为协议的唯一部分被描述为特定字符,你已经知道了字节值,因此可以明确指定。

要为数据报建立byte[],我建议您使用MemoryStream(您也可以使用BinaryWriter来处理更复杂的数据类型,但在这里您只是处理字节... BinaryWriter使用自己的长度前缀格式的字符串,因此无论如何你必须转换为byte[]字符串。像下面这样的东西应该有效:

byte[] GetMasterServerQueryDatagram(byte regionCode, string address, string filter)
{
    MemoryStream stream = new MemoryStream();

    stream.WriteByte(0x31);
    stream.WriteByte(regionCode);
    byte[] stringZero = Encoding.ASCII.GetBytes(address + "\0");
    stream.Write(stringZero, 0, stringZero.Length);
    stringZero = Encoding.ASCII.GetBytes(filter + "\0");
    stream.Write(stringZero, 0, stringZero.Length);

    return stream.ToArray();
}

注意:

  • 您可能希望根据Valve文档中的表声明enum来表示regionCode值,以便您的其他代码可以按名称引用该区域。
  • 密切关注您传递"0.0.0.0:0"作为第一个IP:port值的文档中的要求,但随后传递其后续服务器返回的 last 值查询。