Я бился головой о свой код большую часть дня и совершенно сбит с толку. По сути, исходный игровой движок имеет задокументированный протокол для своего 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();
}
}
2 ответа
Вы использовали Wireshark?
Этот инструмент необходим, когда вы пытаетесь скопировать / реконструировать существующие протоколы. Просто выполните обычную аутентификацию с заведомо работающим клиентом и сохраните журнал. Затем используйте свой собственный код и попытайтесь увидеть, где биты, отправленные по сети, отличаются от битов в журнале.
Иногда это довольно сложно увидеть, просто взглянув на код, например, вставку '\ n' в неправильном месте или дополнительную строку после всего сообщения.
У меня была похожая проблема некоторое время назад
В вашей функции ответа:
using (NetworkStream clientStream = client.GetStream())
(...)
Причиной может быть удаление clientStream. В моем случае удаление потока вызвало разрыв соединения, GetStream () не возвращает новый экземпляр потока, он возвращает поток, принадлежащий TCPClient. Посмотрим, поможет ли это.
Похожие вопросы
Новые вопросы
c#
C# (произносится как «see Sharp») — это высокоуровневый мультипарадигменный язык программирования со статической типизацией, разработанный Microsoft. Код C# обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, которое включает в себя .NET, .NET Framework, .NET MAUI и Xamarin среди прочих. Используйте этот тег для ответов на вопросы о коде, написанном на C#, или о формальной спецификации C#.