簡體   English   中英

C#TCP服務器回復數據包問題

[英]C# TCP Server Reply Packet Issue

在一天中的大部分時間里,我一直在朝着我的代碼狂奔,我完全陷入了困境。 基本上,源游戲引擎的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();
    }
}

您一直在使用Wireshark嗎?

當您嘗試復制/反向工程現有協議時,此工具必不可少。 只需使用已知正常工作的客戶端進行普通身份驗證並保存日志即可。 然后使用您自己的代碼,嘗試查看線路上發送的位與日志中的位不同。

有時僅通過查看代碼就很難看到,例如在錯誤的位置插入了“ \\ n”,或者在整個消息后加了一行

我前段時間也遇到過類似的問題

在您的Reply函數中:

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

丟棄clientStream可能是罪魁禍首。 在我的情況下,流的處置導致連接終止,GetStream()不返回流的新實例,而是返回TCPClient擁有的Stream。 看看是否有幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM