我正在使用 C# TCP 客户端并使用 Microsoft 网络监视器监视我的数据包。有一个服务器基本上是一个黑匣子,发送 N 个数据包(现在它的数量级为 10-20),每个数据包与下一个数据包之间的延迟为 0.1 毫秒到 1 毫秒。
我的客户端读取的数据包是有序的,当然大多数到达的数据块比网络监视器上出现的数据块更大,因为 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()
基本上转换消息并将其添加到列表的方法。(它返回 true 或 false ,因为它实际上是要进入 if 子句,但直到我摆脱这个实际上没有任何用途的问题)
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;
}
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()
//*******************************************************************
}