1

在一天的大部分时间里,我一直在用头撞我的代码,我完全被难住了。基本上,源游戏引擎有一个记录在案的 RCON(网络上的远程控制台?)协议,我正在尝试复制它。有数百个示例,但所有示例都来自客户端(建立与游戏服务器的 RCON 的连接),因为我正在尝试实际重新创建服务器部分以回复客户端。

这是有关 RCON 协议的信息。我遇到的代码问题是,当我收到身份验证请求时,一切都很好。当我尝试回复它并确定连接时,连接失败。所以我在回复时做错了,但不确定是什么。

http://developer.valvesoftware.com/wiki/Source_RCON_Protocol

private void ReadClientPacket(object client)
{
    TcpClient tcpClient = (TcpClient)client;
    NetworkStream clientStream = tcpClient.GetStream();

    while (true)
    {
        try
        {
            int packetsize;

            // Create a new Packet Object and fill out the data from the incoming TCP Packets
            RCONPacket packet = new RCONPacket();

            using (BinaryReader reader = new BinaryReader(clientStream))
            {
                // First Int32 is Packet Size
                packetsize = reader.ReadInt32();

                packet.RequestId = reader.ReadInt32();
                packet.RconDataReceived = (RCONPacket.RCONDATA_rec)reader.ReadInt32();

                Console.WriteLine("Packet Size: {0} RequestID: {1} ServerData: {2}", packetsize, packet.RequestId, packet.RconDataReceived);

                // Read first and second String in the Packet (UTF8 Null Terminated)
                packet.String1 = ReadBytesString(reader);
                packet.String2 = ReadBytesString(reader);

                Console.WriteLine("String1: {0} String2: {1}", packet.String1, packet.String2);

                switch (packet.RconDataReceived)
                {
                    case RCONPacket.RCONDATA_rec.SERVERDATA_AUTH:
                    {
                        ReplyAuthRequest(packet.RequestId, tcpClient);
                        break;
                    }
                    case RCONPacket.RCONDATA_rec.SERVERDATA_EXECCOMMAND:
                    {
                        //ReplyExecCommand(packet.RequestId, tcpClient);
                        break;
                    }
                    default:
                    {
                        break;
                    }
                }
            }

            break;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            break;
        }
    }

    tcpClient.Close();
}

private void ReplyAuthRequest(int RequestID, TcpClient client)
{
    Console.WriteLine("Replying to Auth Request");

    // Authentication Reply
    using (NetworkStream clientStream = client.GetStream())
    using (MemoryStream stream = new MemoryStream())
    using (BinaryWriter writer = new BinaryWriter(stream))
    {
        writer.Write((int)10); // Packet Size
        writer.Write(RequestID); // Mirror RequestID if Authenticated, -1 if Failed
        writer.Write((int)RCONPacket.RCONDATA_sent.SERVERDATA_AUTH_RESPONSE);
        writer.Write(ConvertStringToByteArray("" + char.MinValue));
        writer.Write(ConvertStringToByteArray("" + char.MinValue));
        byte[] buffer = stream.ToArray();
        Console.WriteLine("size of full auth response packet is {0}", buffer.Length);

        clientStream.Write(buffer, 0, buffer.Length);
        clientStream.Flush();
    }
}
4

2 回答 2

0

你一直在使用Wireshark吗?

当您尝试复制/逆向工程现有协议时,此工具必不可少。只需使用已知工作的客户端进行正常身份验证并保存日志。然后使用您自己的代码并尝试查看在线上发送的位与日志中的位不同的地方。

有时仅通过查看代码就很难看到一些事情,例如在错误的位置插入了“\n”,或者在整个消息之后增加了一行

于 2011-03-14T01:03:35.903 回答
0

我前段时间遇到过类似的问题

在您的回复功能中:

using (NetworkStream clientStream = client.GetStream())
(...)

clientStream 的处置可能是罪魁祸首。在我的情况下,流的处理导致连接终止,GetStream() 不返回流的新实例,它返回 TCPClient 拥有的 Stream。看看是否有帮助。

于 2011-03-14T01:26:09.200 回答