Hallo zusammen,
vielleicht kann mir ja Jemand von euch weiterhelfen.
Ich habe einen Server, welcher den Zugriff auf die Datenbank ausübt und einen Client, der mittels API Daten vom Server abfragt. Dabei werden Objekte beim Versand mittels Base64 serialisiert und beim Empfänger wieder deserialisiert.
Soweit so gut, doch nun gibt es größere Objekte, welche je nach Bandbreite unterschiedlich lange für den Empfang brauchen. Nun habe ich das Problem, dass hier nun die Übertragung aufgrund eines manuellen Timeouts abgebrochen wird. Hier mal eine Funktion der API:
Das Timeout ist hier 3 Sekunden. Die Übertragung dauert allerdings ca 6 Sekunden. Nun möchte ich nicht einfach das Timeout höher setzen, sondern er soll einfach solange das Timeout wiederholen, bis die Nachricht empfangen wurde oder noch ein Empfang einer Nachricht stattfindet.
Mein Ansatz sieht hier so aus:
Der Empfang findet in einem Separaten Thread statt. Das Flag
Verabeitet wird die Nachricht dann, wenn der Delimiter erkannt worden ist. Dies geschieht durch das Hinzufügen zur NachrichtenQueue.
Wobei NachrichtenQueue wie folgt dargestellt wird
QueueAbarbeiten wird ebenfalls in einem neuen Thread ausgeführt, damit ich in Events erneute Anfragen an den Server senden kann, ohne meinen Empfangsthread zu blockieren.
QueueAbrabeiten dequeued die Nachricht nun und ruft das abonnierte Event NachrichtReceived auf.
Hat Jemand eine Idee, wie ich das ganze lösen kann?
LG
vielleicht kann mir ja Jemand von euch weiterhelfen.
Ich habe einen Server, welcher den Zugriff auf die Datenbank ausübt und einen Client, der mittels API Daten vom Server abfragt. Dabei werden Objekte beim Versand mittels Base64 serialisiert und beim Empfänger wieder deserialisiert.
Soweit so gut, doch nun gibt es größere Objekte, welche je nach Bandbreite unterschiedlich lange für den Empfang brauchen. Nun habe ich das Problem, dass hier nun die Übertragung aufgrund eines manuellen Timeouts abgebrochen wird. Hier mal eine Funktion der API:
C#-Quellcode
- public Aufgabe GetAufgabe(long A_NR, bool istAktiveAufgabe = true)
- {
- if (!IsLoggedIn)
- throw new Exceptions.LoginRequiredException("Aktion erfordert Login am AufgabenServer. Bitte loggen Sie sich ein.");
- var clientProtokoll = new ClientProtokoll<RequestAufgabeNachricht>(new RequestAufgabeNachricht(A_NR, istAktiveAufgabe));
- Stopwatch watch = new Stopwatch();
- Aufgabe result = null;
- bool empfangen = false;
- EventWaitHandle ewh = new EventWaitHandle(false, EventResetMode.AutoReset);
- void handler(object sender, CustomEventArgs e)
- {
- if (e.AnfrageId == clientProtokoll.AnfrageId)
- {
- if (e.Nachricht is ServerProtokoll<ObjectNachricht> objNachricht)
- {
- watch.Stop();
- empfangen = true;
- result = (Aufgabe)objNachricht.Nachricht.Value;
- ewh.Set();
- }
- }
- }
- NachrichtenQueue.NachrichtReceived += handler;
- watch.Start();
- clientProtokoll.Send(ServerConnection.Connection);
- ewh.WaitOne(Timeout);
- NachrichtenQueue.NachrichtReceived -= handler;
- Debug.WriteLine("Antwort erhalten in: " + watch.ElapsedMilliseconds + " ms");
- return result;
- }
Das Timeout ist hier 3 Sekunden. Die Übertragung dauert allerdings ca 6 Sekunden. Nun möchte ich nicht einfach das Timeout höher setzen, sondern er soll einfach solange das Timeout wiederholen, bis die Nachricht empfangen wurde oder noch ein Empfang einer Nachricht stattfindet.
Mein Ansatz sieht hier so aus:
Der Empfang findet in einem Separaten Thread statt. Das Flag
IsReceivingData
wird dabei wie folgt gesetzt:C#-Quellcode
- List<byte> bytesReceived = new List<byte>();
- while (IsConnected && !stop)
- {
- try
- {
- // Stream zum lesen holen
- while (Connection.Available > 0 && Connection.Connected)
- {
- IsReceivingData = true;
- int size = (Connection.Available > Int32.MaxValue) ? Int32.MaxValue : Connection.Available;
- byte[] nextByte = new byte[size];
- Connection.Receive(nextByte, 0, size, SocketFlags.None);
- bytesReceived.AddRange(nextByte);
- }
- Thread.Sleep(10); // Nach jedem Durchgang warten wir 10ms, damit die CPU Auslastung nicht durchs permanente Abfragen bis auf 100% ansteigt!
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- File.AppendAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "error.log"), ex.Message + Environment.NewLine);
- bytesReceived.Clear();
- }
- // Prüfen ob eine Nachricht vollständig angekommen ist
- if (bytesReceived.Contains(GlobaleVariabeln.Delimiter))
- {
- // Wir müssen an dieser Stelle prüfen ob wir mehr als eine Nachricht vollständig empfangen haben.
- int delimiterPos = bytesReceived.IndexOf(GlobaleVariabeln.Delimiter);
- byte[] data = bytesReceived.GetRange(0, delimiterPos).ToArray();
- bytesReceived.RemoveRange(0, delimiterPos + 1);
- NachrichtenQueue.Enqueue(data);
- IsReceivingData = bytesReceived.Count > 0;
- }
- }
Verabeitet wird die Nachricht dann, wenn der Delimiter erkannt worden ist. Dies geschieht durch das Hinzufügen zur NachrichtenQueue.
Wobei NachrichtenQueue wie folgt dargestellt wird
public sealed class NachrichtenQueue : Queue
.QueueAbarbeiten wird ebenfalls in einem neuen Thread ausgeführt, damit ich in Events erneute Anfragen an den Server senden kann, ohne meinen Empfangsthread zu blockieren.
QueueAbrabeiten dequeued die Nachricht nun und ruft das abonnierte Event NachrichtReceived auf.
Hat Jemand eine Idee, wie ich das ganze lösen kann?
LG