Entwickler-Ecke
ASP.NET und Web - Meine POP3-Abfrage ist zu schnell
jasocul - Fr 16.06.06 08:41
Titel: Meine POP3-Abfrage ist zu schnell
Zuerst mal ein bisschen Source:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42:
| public string SendCommand(string Command) { string ReturnResult = string.Empty; int countReceive = 0; try { srClient.DiscardBufferedData(); LogEntry(Command); swClient.WriteLine(Command); do { countReceive = cClient.Available; System.Threading.Thread.Sleep(100); } while (countReceive != cClient.Available); while (srClient.Peek() > -1) { if (ReturnResult != string.Empty) ReturnResult += Environment.NewLine; ReturnResult += srClient.ReadLine(); } LogEntry(ReturnResult); return ReturnResult; } catch (Exception ex) { throw new Exception("Befehl fehlgeschlagen. Server meldet: " + ReturnResult + Environment.NewLine + ex.Message); } } |
Die Problemstelle habe ich im Source kommentiert.
Die Lösung mit dem Sleep ist nur provisorisch. Bei einem DSL-Anschluss funtioniert es so meistens(!). Bei einer analogen Leitung eher selten.
Ohne Sleep funktioniert es meistens gar nicht, weil die Daten nicht schnell genug bereit stehen. Das Programm ist an der Stelle einfach zu schnell. :mrgreen:
Vermutlich muss ich irgendwie über den TimeOut gehen. Allerdings kann ich ja auch nicht bis zum TimeOut warten um dann zu merken, dass keine Daten mehr kommen.
Wer nimmt mir mal das Brett vom Kopf weg, damit das funktioniert?
tommie-lie - Fr 16.06.06 12:30
Titel: Re: Meine POP3-Abfrage ist zu schnell
Ich habe zwar noch nicht mit Sockets gearbeitet, aber dein Vorgehen kommt mir ein wenig spanisch vor.
C#-Quelltext
1: 2: 3: 4: 5:
| do { countReceive = cClient.Available; } while (countReceive != cClient.Available); |
Lassen wir das Sleep einfach weg, steht da: "Setze meine Variable auf einen bestimmten Wert. Wenn meine Variable nicht den bestimmten Wert hat, tue das gleiche nochmal.
Das erinnert ein wenig an
C#-Quelltext
1: 2: 3: 4:
| do { int i = 42; } while (i != 42) |
Daß diese eine Überprüfung einige hundert MAle schneller ist, als das Empfangen über den TCP-Client, egal welche Anbindung du hast, leuchtet schnell ein, denn das ist eine Operation die in Assembler wenige Takte benötigt (das Aufrufen der Methode schon eingerechnet).
Dein Warten auf neue verfügbare Daten ist bei diesem Vorgehen also zwingend notwendig.
Vielleicht möchtest du System.Net.Sockets.NetworkStream verwenden, der eine Eigenschaft NetworkStream.DataAvailable hat zu deren Verwendung es in der Referenzdoumentation ein Beispiel gibt:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| if(myNetworkStream.CanRead){ byte[] myReadBuffer = new byte[1024]; StringBuilder myCompleteMessage = new StringBuilder(); int numberOfBytesRead = 0;
do{ numberOfBytesRead = myNetworkStream.Read(myReadBuffer, 0, myReadBuffer.Length);
myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead)); } while(myNetworkStream.DataAvailable);
Console.WriteLine("You received the following message : " + myCompleteMessage); } else{ Console.WriteLine("Sorry. You cannot read from this NetworkStream."); } |
Sieht für mich deutlich eleganter aus, als deine Lösung.
jasocul - Fr 16.06.06 12:40
Die Schleife sieht nur im ersten Moment merkwürdig aus.
Die Eigenschaft Available ändert sich ständig (zumindest bei mir) bis die Gesamtgröße bekannt ist. Durch diese Schleife wollte ich sicher stellen, dass mit dem Lesen der Daten erst begonnen wird, wenn alles verfügbar ist.
Ich meine, dass ich die andere Variante auch schonmal getestet habe, aber bei der vielen Experimentiererei kann ich mich auch irren. Ich werde es auf jeden Fall nochmal prüfen.
tommie-lie - Fr 16.06.06 13:00
jasocul hat folgendes geschrieben: |
Die Schleife sieht nur im ersten Moment merkwürdig aus.
Die Eigenschaft Available ändert sich ständig (zumindest bei mir) bis die Gesamtgröße bekannt ist. |
Ja, das dachte ich mir schon, aber "ständig" ist relativ. Nach der Zuweisung dürfte der Test die nächste Operation sein, die ausgeführt wird. Innerhalb eines einzigen Taktes (in der Größenordnung einer Nanosekunde) ist es unwahrscheinlich, daß sich der Wert von Available ändert. Wie gesagt, die gesamte Schleife wird nicht länger sein als einige (wenige) Takte, sofern der Socketpuffer asynchron arbeitet (wovon ich ausgehe, weil alles andere unsinnig wäre), es ist einfach unwahrscheinlich, daß sich der Wert in dieser kurzen Zeit ändert, schließlich kommst du erst mit 1000Base-*-Ethernet in die Größenordnung von einer Nanosekunde pro
Bit, nicht aber pro Frame. Mit DSL wirst du alle paar zigtausend Prozessortakte einen Frame empfangen, weshalb du deine Schleife irgendwie künstlich ausbremsen musst, oder auf eine andere Datenendeerkennungsmethode ausweichen musst. Da ich nicht so der Netzwerker bin (zumindest nicht auf Seite der Implementierung), kann ich dir aber leider nicht sagen, wie die klassische Herangehensweise an dieses Problem ist.
jasocul - Fr 16.06.06 13:20
Deswegen ist das auch nur eine provisorische Lösung gewesen, damit ich erstmal weiter programmieren kann. Für die Firmenleitung haben die 100ms gereicht, aber auch dann die Lösung ist einfach nicht akzeptabel. Deswegen habe ich das Topic ja erstellt. :wink:
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!