2012-11-20 3 views
2

У меня есть следующий метод, который отправляет команду rcon игровому серверу.C# udp socket не получает целое сообщение

public string sendCommand(string command) 
{ 
byte[] bufferTemp = Encoding.ASCII.GetBytes(command); 
byte[] bufferSend = new byte[bufferTemp.Length + 4]; 

//big enough to receive response 
byte[] bufferRec = new byte[65000]; 

//intial 4 characters as per standard 
bufferSend[0] = byte.Parse("255"); 
bufferSend[1] = byte.Parse("255"); 
bufferSend[2] = byte.Parse("255"); 
bufferSend[3] = byte.Parse("255"); 
int j = 4; 

for (int i = 0; i < bufferTemp.Length; i++) 
{ 
    bufferSend[j++] = bufferTemp[i]; 
} 

//send rcon command and get response 
try 
{ 
    this.server.Socket.Send(bufferSend, SocketFlags.None); 
    this.server.Socket.Receive(bufferRec); 
} 
catch (SocketException e) 
{ 
    MessageBox.Show(e.ToString(), "Error occured"); 
} 

string response = Encoding.ASCII.GetString(bufferRec); 

return response; 
} 

из всех команд, я могу, возможно, отправить, 1 из них возвращает намного больше данных, чем другие, и, кажется, что * buffer_rec * байтовый массив получает только около 1/4 из сообщения, но массив был объявлен достаточно большим, чтобы содержать все данные. В последующих трех запросах остальная часть данных выводится, как если бы она была забуферирована каким-то образом.

Я не знаю, почему это происходит. Если да, не могли бы вы сообщить мне, как исправить эту проблему?

Спасибо Crouz

+1

'Метод приема считывает данные в параметр буфера и ** возвращает количество успешно прочитанных байтов **' http://msdn.microsoft.com/en-us/library/8s4y8aff.aspx –

+0

I знаю, что это так, но мне не известно, сколько байтов должно быть полностью возвращено сервером, поэтому я не знаю, когда я закончил читать данные, которых боюсь. – Crouzilles

+2

@ user1834208: Даже в стороне от этого, вы должны * всегда * использовать возвращаемое значение. В настоящий момент вы создаете строку из * целого * 'bufferRec', независимо от того, сколько данных было прочитано. Не делай этого. Затем вы должны использовать что-то вроде Wireshark, чтобы увидеть, что на самом деле происходит в сети. –

ответ

-2

Хорошо, кажется, что после 6 часов, глядя на это, я, наконец, придумать решение, поэтому здесь небольшое изменение, внесенное в получении данных, обратите внимание на нить спать в течение 10 мс это, похоже, необходимо для своевременного поступления датаграмм.

//send rcon command and get response 
    string response = ""; 
    try 
    { 
     this.server.Socket.Send(bufferSend, SocketFlags.None); 

     do 
     { 
      int bytesReceived = this.server.Socket.Receive(bufferRec); 
      response += Encoding.ASCII.GetString(bufferRec, 0, bytesReceived); 
      System.Threading.Thread.Sleep(10); 
     } while (this.server.Socket.Available > 0); 
    } 
    catch (SocketException e) 
    { 
     MessageBox.Show(e.ToString(), "Error occured"); 
    } 

Если вы думаете, что это лучший или более элегантный способ обработки этого, не стесняйтесь, чтобы хлопнуть мой код, но сделать это, предлагая альтернативу, как я всегда рад узнать что-то новое. С уважением, Crouz

+0

Хорошо, я буду кусать. Это работает случайно.Вам действительно нужно переработать свой протокол, чтобы содержать заголовок, который сигнализирует длину сообщения, и читать до тех пор, пока у вас не будет такого количества байтов, или не определите какой-либо разделитель «конец сообщения», чтобы ваш код анализа сообщений знал, когда он сообщение. Также обратите внимание, что в настоящее время у вас нет нулевой защиты от повреждения пакетов (вам нужно реализовать какую-то контрольную сумму для этого) или переупорядочение (если вам все равно, вам нужно реализовать какой-то порядковый номер). Или просто используйте TCP, и вы получите много всего выше. – tomfanning

+1

Остается ключ «Метод приема» считывает данные в параметр буфера и ** возвращает количество успешно прочитанных байтов ** ». Ваш цикл для приема байтов должен просто добавлять эти байты в буфер. Затем ** отдельно **, вы должны изучить этот буфер, чтобы узнать, есть ли у вас одно или несколько полных сообщений для обработки. («Полное сообщение» соответствует вашему дизайну протокола.) Когда у вас есть сообщение, удалите ** только эти байты ** из буфера, выполните любую обработку, которую вам нужно сделать (запустите событие, что угодно), затем запустите цикл снова. – tomfanning

+0

Я не разработал протокол quake3, поэтому я не могу вносить в него изменения, чтобы сообщить, как долго я буду бояться сообщения. В основном я не контролирую серверную сторону. Я использовал wirehark для проверки пакета, нигде я не вижу длину сообщения и маркер сообщения (помните, я очень новичок в wirehark, я мог бы что-то пропустить). – Crouzilles

Смежные вопросы