1

私は一日の大半を自分のコードに頭をぶつけていましたが、完全に困惑しています。基本的に、ソース ゲーム エンジンには、再現しようとしている RCON (Remote Console Over Network?) 用の文書化されたプロトコルがあります。何百もの例がありますが、それらはすべてクライアント側 (ゲーム サーバーの 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 が所有するストリームを返します。それが役立つかどうかを確認してください。

于 2011-03-14T01:26:09.200 に答える