Erster Hintergrund. Ich habe eine Kamera, mit der meine App über ein Ethernetkabel verbunden ist, und sie führt Operationen basierend auf Befehlen aus, die ich sende und antwortet mit Befehlen zurück.Schnelle Paketverarbeitung aus Stream
Wenn ich den Kameraauslösebefehl als Beispiel nehme. Die Kamera wird ein Bild machen, wenn ich es 'T1' sende. Alle Befehle verwenden, um eine Start- und Ziel char den Beginn und das Ende des Pakets zu markieren, so die volle Paket Ich mag dieses
(char) 0x02T1 (char) 0x03
mit (char) 0x02 als Start aussehen senden von Paket und (char) 0x03 als das Ende der Packung.
Die Kamera nimmt dann ein Bild auf und sendet den gleichen Befehl zurück, um zu sagen, dass es erledigt ist. Sie können die Kamera auch so einstellen, dass sie Daten zurücksendet, wenn sie das Bild aufgenommen hat. In meinem Fall habe ich die Kamera inspizieren ein paar Bereiche und ich möchte einige Werte von der Inspektion.
So ist die Rückkehr der Kamera wäre so etwas wie ‚T1‘ und dann sagen ‚1,1,500,20,300‘
On für das Problem. Ich benutze eine TcpClient
und eine NetworkStream
für die Kommunikation, aber ich habe Probleme mit der Verarbeitung der Pakete auf der Empfängerseite. Ich habe verschiedene Methoden ausprobiert, aber sie scheinen langsam zu sein oder garantieren nicht, dass ich alle Daten bekomme.
Zuerst brauche ich etwas, das alle Daten liest und sicherstellen, dass ich alle Daten habe.
Zweitens brauche ich etwas, das die Daten verarbeiten und in Pakete aufteilen kann und dies so schnell wie möglich tun.
Dies ist nur eine Methode, die ich versucht habe und volle Anerkennung geht an die Person, die die StreamReaderExtensions
gemacht hat. Ich bin sicher, ich habe es irgendwo hier gefunden.
internal static class StreamReaderExtensions
{
public static IEnumerable<string> ReadUntil(this StreamReader reader, string delimiter)
{
List<char> buffer = new List<char>();
CircularBuffer<char> delim_buffer = new CircularBuffer<char>(delimiter.Length);
while (reader.Peek() >= 0)
{
char c = (char)reader.Read();
delim_buffer.Enqueue(c);
if (delim_buffer.ToString() == delimiter)
{
if (buffer.Count > 0)
{
yield return new String(buffer.ToArray());
buffer.Clear();
}
continue;
}
buffer.Add(c);
}
}
private class CircularBuffer<T> : Queue<T>
{
private int _capacity;
public CircularBuffer(int capacity)
: base(capacity)
{
_capacity = capacity;
}
new public void Enqueue(T item)
{
if (base.Count == _capacity)
{
base.Dequeue();
}
base.Enqueue(item);
}
public override string ToString()
{
List<String> items = new List<string>();
foreach (var x in this)
{
items.Add(x.ToString());
};
return String.Join("", items);
}
}
}
und meine Prozessmethode. _stream
ist TcpClient.GetStream()
public static class Constants
{
public const char StartOfPacket = (char)0x02;
public const char EndOfPacket = (char)0x03;
}
private IEnumerable<string> ProcessResponse()
{
var streamReader = new StreamReader(_stream);
var packets = streamReader.ReadUntil(new string(new char[] {Constants.EndOfPacket}));
return packets;
}
Sie sollten pro Char lesen. Lies einfach einen großen Block und überprüfe die erhaltene Größe. Analysieren Sie den Block, bis Sie das Trennzeichen gefunden haben, und entfernen Sie den analysierten Block. Wiederholen Sie dies, bis Sie halbe Pakete haben. –
@ JeroenvanLangen halbe Pakete? – Gaz83
könnte eine Nachricht in mehrere Pakete aufgeteilt werden. Dies liegt daran, dass es sich um einen Stream anstelle eines Datagramms handelt. Wenn Sie nur 1 Char zu der Zeit erhalten, ist es immer in mehrere geteilt, –