Проблема с ответным пакетом сервера C # TCP - PullRequest
1 голос
/ 14 марта 2011

Я бился головой о своем коде большую часть дня, и я совершенно ошеломлен.По сути, исходный игровой движок имеет документированный протокол для своего 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();
    }
}

Ответы [ 2 ]

0 голосов
/ 14 марта 2011

У меня была похожая проблема некоторое время назад

В вашей функции ответа:

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

Уничтожение clientStream может быть виновником.В моем случае удаление потока вызвало разрыв соединения, GetStream () не возвращает новый экземпляр потока, а возвращает поток, принадлежащий TCPClient.Посмотрим, поможет ли это.

0 голосов
/ 14 марта 2011

Использовали ли вы Wireshark ?

Этот инструмент необходим, когда вы пытаетесь скопировать / перепроектировать существующие протоколы.Просто выполните обычную аутентификацию с помощью известного работающего клиента и сохраните журнал.Затем используйте свой собственный код и попытайтесь увидеть, где биты, передаваемые по проводам, отличаются от битов в журнале.

Иногда это довольно сложно увидеть, просто взглянув на код, например '\ n'вставка не в ту точку или дополнительную строку после всего сообщения

...