1

我将很久以前编写的 C++ 应用程序中的一些代码转换为 C#。在 C++ 中,我使用了一个有点缓冲的库,但是我缺乏 C# 知识使得转换有些复杂。

当我查询我的应用程序时,我只是使用 ByteWriter 而没有正确转换任何值(就像 bf.Write(-1) 和 bf.Write("stringhere") 查询程序至少查询它,只是得到错误的信息。当我正确地转换了值(长,字节,短等)它完全破坏了,查询应用程序甚至不再看到它了。

C++ 代码片段

void PlayerManager::BuildReplyInfo()
{   
    // Delete the old packet
    g_ReplyInfo.Reset();

    g_ReplyInfo.WriteLong(-1);
    g_ReplyInfo.WriteByte(73);
    g_ReplyInfo.WriteByte(g_ProtocolVersion.GetInt());
    g_ReplyInfo.WriteString(iserver->GetName());    
    g_ReplyInfo.WriteString(iserver->GetMapName()); 
    g_ReplyInfo.WriteString(gGameType);
}

C# 代码

public static byte[] ConvertStringToByteArray(string str)
{
    System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
    return encoding.GetBytes(str);
}

//------------------------------------

    while (true)
    {
        data = new byte[1024];
        recv = socket.ReceiveFrom(data, ref Remote);

        Console.WriteLine("Message length is " + recv);

        // If the length is 25 and the 5th byte is 'T' it is a A2S_INFO QUERY
        if (recv == 25 && data[4] == 84)
        {
            Console.WriteLine("Source Engine Query!");

            data = BuildReplyInformation();
            socket.SendTo(data, 0, data.Length, SocketFlags.None, Remote);
        }
    }
}

public static byte[] BuildReplyInformation()
{
    MemoryStream stream = new MemoryStream();
    BinaryWriter writer = new BinaryWriter(stream);

    writer.Write((long)(-1));
    writer.Write((byte)(73)); // Steam Version
    writer.Write((byte)(15)); // Protocol
    writer.Write(ConvertStringToByteArray("Minecraft Server\0")); // Hostname
    writer.Write(ConvertStringToByteArray("Map Name\0")); // Map Name
    writer.Write(ConvertStringToByteArray("tf\0")); // Game Directory
    writer.Write(ConvertStringToByteArray("Minecraft Server\0")); // Game Description
    writer.Write((short)(440));
    writer.Write((byte)(15)); // Players
    writer.Write((byte)(32)); // Max Players
    writer.Write((byte)(0)); // Bots
    writer.Write((byte)(100));
    writer.Write((byte)(119)); // 108 Linux, 119 Windows
    writer.Write((byte)(0)); // Password Boolean
    writer.Write((byte)(01)); // Vac Secured
    writer.Write(ConvertStringToByteArray("1.1.3.7\0"));

    return stream.ToArray();
}
4

3 回答 3

0

C# 中的长尺寸与 C++ 不同,解决了该问题。

于 2011-03-12T12:00:18.797 回答
0

一些可能会让你走上正轨的想法:

  1. 您确定需要 UTF8 作为字符串编码吗?
  2. 当您查看数组并将其与预期结构进行比较时,您是否能够找出数组在什么时候不符合标准?
于 2011-03-12T08:42:35.653 回答
0

只需记住几件事:

  1. UTF-8 字符串有时以 BOM(字节顺序标记)开头,有时则不是。
  2. 字符串有时以序列化长度为前缀,有时以空值结尾。

我的建议是仔细检查原始 C++ 方法 WriteString(...) 以了解它相对于 #1 和 #2 的行为,然后再检查 C# 方法 GetBytes(...) 是否相同. 如果我记得,.NET 二进制序列化程序会为每个写入的字符串写入以长度为前缀的字符串,但 UTF8 编码器不会(也不输出空字符)。UTF8 编码器也可能(取决于您如何使用它?)输出 BOM。

另外,我怀疑在通过 UTF8 编码器时如何写出 \0 。您可能(为了踢球)尝试将空标记与字符串内容分开输出,作为一个 0 值字节。

于 2011-03-12T08:50:11.317 回答