Я работаю над клиентом C# TCP и отслеживаю свои пакеты с помощью Microsoft Network Monitor. Существует сервер, который в основном представляет собой черный ящик, посылает N количество пакетов (сейчас он находится в порядке 10-20) с задержкой от 0,1 мс до 1 мс между каждым из них и следующим.Socket не читает все входящие пакеты
Пакеты, которые читаются моим клиентом, находятся в порядке и, конечно, чаще всего поступают в более крупные куски, чем в Network Monitor, поскольку TCP получает поток. Моя проблема заключается в том, что некоторые пакеты не приходят (я проверял предыдущий фрагмент информации, чтобы убедиться, что его нет). Они также не хранятся в неправильном порядке.).
Возможно ли, что у моего клиента какая-то информация отсутствует? Часто ли отправляются пакеты? К сожалению, я не могу вмешиваться в их частоту. Я добавляю здесь некоторые из моего кода, если бы вы могли рассказать мне, почему пакеты, которые прибывают, не читаются, и как это решить, я был бы очень благодарен.
Это где я первый называют BeginReceive:
private static void AcceptCallback(IAsyncResult result)
{
ConnectionInfo connection = new ConnectionInfo();
MensajeRecibido msj = new MensajeRecibido();
try
{
// Finish Accept
Socket s = (Socket)result.AsyncState;
connection.Socket = s.EndAccept(result);
msj.workSocket = connection.Socket;
connection.Socket.Blocking = false;
connection.Buffer = new byte[255];
lock (connections) connections.Add(connection);
// Start Receive
connection.Socket.BeginReceive(msj.buffer, 0,
msj.buffer.Length, SocketFlags.None,
new AsyncCallback(ReceiveCallback), msj);
// Start new Accept
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), result.AsyncState);
}
catch (SocketException exc)
{
//Log here
}
catch (Exception exc)
{
//Log here
}
}
Это обратный вызов:
private async static void ReceiveCallback(IAsyncResult result)
{
MensajeRecibido mensaje = new MensajeRecibido();
mensaje = (MensajeRecibido)result.AsyncState;
try
{
mensaje.workSocket.EndReceive(result);
mensaje.EstaCompleto();
mensaje.workSocket.BeginReceive(mensaje.buffer, 0,
mensaje.buffer.Length, SocketFlags.None,
new AsyncCallback(ReceiveCallback), mensaje);
}
catch (SocketException)
{
//Log
}
catch (Exception)
{
//Log
}
}
И это метод EstaCompleto()
, который в основном преобразует сообщение и добавляет его к списку. (Он возвращает истину или ложь, потому что это на самом деле означает идти в, если п, но пока я не избавиться от этой проблемы, которая на самом деле не служит никакой цели)
public bool EstaCompleto()
{
MensajeActual = Destuffing(ByteToFrame_Decoder(buffer)); //This translates the message to an understandable string
Mensajes.Enqueue(MensajeActual);
if(MensajeActual.Contains("<ETX>"))
{
return true;
}
else return false;
}
Edit 25/3/15: Вот остальная часть класса MensajeRecibido.
public class MensajeRecibido
{
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 25500;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
public string UltimoMensajeLeido = "0";
public string MensajeActual = "0";
public Queue<string> Mensajes = new Queue<string>();
public IPAddress IPRack;
//*******************************************************************
public bool EstaCompleto()
///See code in the previous sample
//*******************************************************************
public string ByteToFrame_Decoder(byte[] frame)
{
string answer = null;
UTF8Encoding ObjDecoder = new System.Text.UTF8Encoding();
char[] array_chares = new char[frame.Length];
string msj_neg = null;
string titlemsg = "Atención";
try
{
int cant = ObjDecoder.GetChars(frame, 0, frame.Length, array_chares, 0);
}
catch (EncoderFallbackException EncFbackEx)
{
msj_neg = "No hay comunicación";
// System.Windows.Forms.MessageBox.Show(msj_neg, titlemsg, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
answer = decode_string(array_chares);
return answer;
} // fin método ByteToFrame_Decoder()
//*******************************************************************
public string Destuffing(string msjstuff)
{
string destuffed = null;
string matched = null;
string original = null;
int largo = msjstuff.Length;
for (int i = 0; i < (largo - 1); i++)
{
matched = msjstuff.Substring(i, 2);
original = msjstuff.Substring(i, 1);
if (original != " ")
{
switch (matched)
{
case "EX":
{ original = "D"; i++; } break;
case "ex":
{ original = "d"; i++; } break;
case "EE":
{ original = "E"; i++; } break;
case "ee":
{ original = "e"; i++; } break;
case " ":
{ original = ""; i += 2; } break;
}
destuffed = destuffed + original;
}
else
{
i++;
}
}
destuffed = destuffed + ">";
return destuffed;
} //fin método Destuffing()
//*******************************************************************
public static string decode_string(char[] ArrChar)
{
string text = null;
string reply = null;
foreach (char letter in ArrChar)
{
int value = Convert.ToInt32(letter);
string hexOutput = String.Format("{0:X}", value); // Convert the decimal value to a hexadecimal value in string form.
switch (hexOutput)
{
case "20":
text = " ";
break;
case "1":
text = "<SOH>";
break;
case "2":
text = "<STX>";
break;
case "3":
text = "<ETX>";
break;
case "4":
text = "<EOT>";
reply = reply + text;
goto Finish;
case "5":
text = "<ENQ>";
break;
case "6":
text = "<ACK>";
break;
case "15":
text = "<NAK>";
break;
case "17":
text = "<ETB>";
break;
case "1E":
text = "<RS>";
break;
/*case "23":
text = "#";
break;
case "24":
text = "$";
break;
case "26":
text = "&";
break;*/
default:
text = letter.ToString();
break;
}
reply = reply + text;
}
Finish: ; //salimos del foreach
return reply;
} //fin método decode_string()
//*******************************************************************
}
Прежде всего, спасибо за минимальную полную ссылку кода, я раньше этого не видел. Было бы трудно воспроизвести его проблему для тех, кто не владеет оборудованием, с которым я общаюсь, и я боюсь, что мне не разрешено использовать IP-адрес для доступа к нему, что является довольно хлопотным. Я сохраняю информацию каждый раз на этих строках: MensajeActual = Destuffing (ByteToFrame_Decoder (buffer)); // Это переводит сообщение в понятную строку Mensajes.Enqueue (MensajeActual); И затем я проверяю очередь, чтобы узнать, что было прочитано. Я не получил два сообщения вместе, как я уже говорил. – Alex
_ «Было бы трудно воспроизвести проблему» _ - тем не менее, для тех, кто может помочь с любым точным ответом, вы должны представить воспроизводимый случай. Если вы не можете, то это не правильный форум для получения помощи. –
_ «Я храню информацию каждый раз на этих строках» _ - нет, не совсем. Тот факт, что вы не используете возвращаемое значение 'EndReceive()', означает, что он является _impossible_, чтобы остальная часть вашего кода работала правильно. Правильная реализация TCP не потеряет «пакеты», период. Если вы считаете, что это происходит, то либо вы имеете неправильную реализацию TCP (например, в «оборудовании»), либо просто не можете распознать объединенные «пакеты» в полученных вами данных. Я считаю последнее более вероятным сценарием, чем первое. –