ich baue eine Verbindung über Socket mit einem Server auf und ziehe Daten.
Dies geschieht jede Sekunde. die Verbindung bleibt natürlich erhalten.
Nun kann es passieren, das mal die Verbindung weg ist. Dann soll dies
festgestellt werden und die Verbindung neu aufgebaut werden.
Mit
if (s.Connected) ...
kann man aber die Trennung bzw den Fehler nicht feststellen, da trotzdem
s.Connected mit true zurückgegeben wird.
Ich möchte jetzt den Fehlversuch darstellen und eine neue Verbindung
aufbauen.
Oder soll ich einfach den nächsten Versuch starten und wenn die Verbindung
wieder da ist, gibt es automatisch ein Ergebniss?
>ich baue eine Verbindung über Socket mit einem Server auf und ziehe Daten.
>Dies geschieht jede Sekunde. die Verbindung bleibt natürlich erhalten.
Gut,...
>Nun kann es passieren, das mal die Verbindung weg ist. Dann soll dies
>festgestellt werden und die Verbindung neu aufgebaut werden.
>Mit
> if (s.Connected) ...
>kann man aber die Trennung bzw den Fehler nicht feststellen, da trotzdem
>s.Connected mit true zurückgegeben wird.
Diese und änliche Fragen wurden schon öfter gestellt. Das Problem ist,
das Socket Verbindungen kein richtiges Event haben, das Dir sagt, das
die Verbindung unterbrochen wurde, sondern ein Timeout, das Du ggf.
einstellen kannst. Mehr dazu in der MSDN/Technet,...
>Ich möchte jetzt den Fehlversuch darstellen und eine neue Verbindung
>aufbauen.
Du musst wohl oder Übel auf ein Timeout warten und das dann abfangen.
>Oder soll ich einfach den nächsten Versuch starten und wenn die Verbindung
>wieder da ist, gibt es automatisch ein Ergebniss?
Das hängt davon ab, wie dein Server arbeitet, ob der mehrere Verbinndungen
zulässt, oder ob er nur eine Verbindung zulässt und diese dann bei Verlust
schliesst, ggf. neustartet,...
Nur nochmal zur Sicherheit: Ist es ein reines "Socket" oder
eine TCPListener/TCPClient Kombination?
Grüße
Kerem
--
-----------------------
Beste Grüsse / Best regards / Votre bien devoue
Kerem Gümrükcü
Latest Project: http://www.codeplex.com/restarts
Latest Open-Source Projects: http://entwicklung.junetz.de
-----------------------
"This reply is provided as is, without warranty express or implied."
> Nur nochmal zur Sicherheit: Ist es ein reines "Socket" oder
> eine TCPListener/TCPClient Kombination?
Bis jetzt ist es ein reines Socket
s = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
jetzt mach ich nach Auftreten des Fehlers ein
s.Shutdown(SocketShutdown.Both);
und eine Neuverbindung, aber irgendwo meckert er, das keine Instanz von s da
wäre.
> Nun kann es passieren, das mal die Verbindung weg ist. Dann soll dies
> festgestellt werden und die Verbindung neu aufgebaut werden.
> Mit
> if (s.Connected) ...
> kann man aber die Trennung bzw den Fehler nicht feststellen, da trotzdem
> s.Connected mit true zurückgegeben wird.
Weil die Connected-Eigenschaft nur den Zustand der Verbindung
während des *letzten* Vorgangs wiedergibt.
Aber Du kannst es schon mit "Connected" machen,
wenn Du z.B. selber etwas sendest. Lies hier
speziell die Hinweise:
[TcpClient.Connected-Eigenschaft (System.Net.Sockets)]
http://msdn.microsoft.com/de-de/library/system.net.sockets.tcpclient.connected.aspx
ciao Frank
--
Dipl.Inf. Frank Dzaebel [MCP/MVP C#]
http://Dzaebel.NET
[Socket.Connected-Eigenschaft (System.Net.Sockets)]
http://msdn.microsoft.com/de-de/library/system.net.sockets.socket.connected.aspx
> ... wobei es hier übrigens vollkomen egal ist,
> ob TcpClient oder Socket.
Das Programm überwacht ein Gerät und wenn die Verbindung ausgefallen ist
soll die Unterbrechung nat. angeezigt werden.
Nach Mölichkeit soll die Verbindung auch automatisch wieder aufgenommen
werden.
Gäbe es dazu evtl. auch andere Möglichkeiten?
Ja gibt es schon.
1.) asynchrone events statt blockierende aufrufe verwenden
2.) immer einen asynchronen receive pending halten
3.) wird die receive Funktion aufgerufen und bytes read ist > 0 dann hat
der server daten geschickt (meistens nach einem request durch den client
oder direkt nach einem Verbindungsaufruf durch den Server ohne
vorherigen request wie etwa eine Welcome-message des Servers). Wenn
bytes read aber 0 ist, dann bedeutet das anspringen der receive Funktion
dass der Server die Verbindung geschlossen hat, dann solltest du noch
einen Shutdown() und einen Close() an dem socket aufrufen.
Wenn Du dann einen automatischen re-connect möchtest, musst du halt
wieder von vorne anfangen mit einem Connect(). Wenn Du das schon
versucht hast und einen error bekommen hast, versuch mal die Socket
Option "reuse socket" zu setzen oder wirf die socket weg und opfere sie
dem GC und instanziere halt ein neues socket.
Wichtig ist jedoch der Grund warum dein Client vom Server disconnected
wird, wenn es nur zum Spaß ist ok, wenn er aber böswillig ist und
einfach keinen Bock hat auf Verbindungen, dann wird wohl auch ein
automatischer re-connect erfolglos bleiben.
Gruß
Peter
> 1.) asynchrone events statt blockierende aufrufe verwenden
Man braucht allerdings keine asynchronen
Events, da die Systematik eigentlich
komplett gleich ist. Stattdessen kann das
alles natürlich auch synchron gehalten werden.
> 2.) immer einen asynchronen receive pending halten
Man führt letztlich - ob synchron oder asynchron -
eine Schleife aus, die ständig eine Aktion auf
dem Socket oder TcpClient ausführt, aus.
Oder wo ein Socket.Poll ausgeführt wird:
[Socket.Poll-Methode (System.Net.Sockets)]
http://msdn.microsoft.com/de-de/library/system.net.sockets.socket.poll.aspx
> Wenn Du dann einen automatischen re-connect möchtest, musst du halt
> wieder von vorne anfangen mit einem Connect().
Ja, das wird in meinem Beispiel so gemacht.
> dann wird wohl auch ein automatischer re-connect
> erfolglos bleiben.
das wurde ja schon öfter erwähnt .
Mit einem synchronen read/rcv blockiert aber die Anwendung,
ein synchroner accept (server) genauso.
>> 2.) immer einen asynchronen receive pending halten
>
> Man führt letztlich - ob synchron oder asynchron -
> eine Schleife aus, die ständig eine Aktion auf
> dem Socket oder TcpClient ausführt, aus.
Mache ich nicht so, ich bevorzuge die asynchronen Funktionen.
> Oder wo ein Socket.Poll ausgeführt wird:
>
> [Socket.Poll-Methode (System.Net.Sockets)]
> http://msdn.microsoft.com/de-de/library/system.net.sockets.socket.poll.aspx
Der Aufruf der asynchronen Funktion wie etwa read/rcv erspart es einem
ja einen
eigenen Poll-Mechanismus zu implementieren. Die asynchrone read/rcv
Funktion etwa erzeugt im Hintergrund einen thread der das pollen macht,
wenn der poll feststellt dass Daten da sind ruft er dann die Methode
auf, die beim Aufruf der asynchronen Methode als Parameter (delegate)
übergeben wurde. Und die Ausführung einer asynchronen Methode blockiert
eben nicht.
>> Wenn Du dann einen automatischen re-connect möchtest, musst du halt
>> wieder von vorne anfangen mit einem Connect().
>
> Ja, das wird in meinem Beispiel so gemacht.
>
>
>
>> dann wird wohl auch ein automatischer re-connect
>> erfolglos bleiben.
>
> das wurde ja schon öfter erwähnt .
>
>
> ciao Frank
Gruß,
Peter
>> Man braucht allerdings keine asynchronen
>> Events, da die Systematik eigentlich komplett gleich ist. Stattdessen
>> kann das
>> alles natürlich auch synchron gehalten werden.
>
> Mit einem synchronen read/rcv blockiert aber die Anwendung,
> ein synchroner accept (server) genauso.
Es blockiert nicht, wenn das in einer Schleife gemacht wird,
das ist recht einfach in meinem "Neuverbinden"-Beispiel
auf meiner Webseite zu sehen.
>> Man führt letztlich - ob synchron oder asynchron - eine Schleife aus, die
>> ständig eine Aktion auf
>> dem Socket oder TcpClient ausführt, aus.
>
> Mache ich nicht so, ich bevorzuge die asynchronen Funktionen.
Intern führen die quasi immer eine Schleife aus.
Es ist dadurch die gleiche Systematik.
>> Oder wo ein Socket.Poll ausgeführt wird:
>>
>> [Socket.Poll-Methode (System.Net.Sockets)]
>> http://msdn.microsoft.com/de-de/library/system.net.sockets.socket.poll.aspx
>
> Der Aufruf der asynchronen Funktion wie etwa read/rcv erspart es einem ja
> einen eigenen Poll-Mechanismus zu implementieren.
Asynchron erspart einem gar nichts. Im Gegenteil,
es ist wesentlich komplizierter.
Intern findet in so einer Lösung immer ein Pollen
statt, um eine Connection zu beobachten,
da ist vollkommen egal ob asynchron oder synchron.
Nein, eine blockierende Funktion blockiert auch in einer Schleife, sie kehrt
dann zurück wenn der Grund für das blockieren nicht mehr gegeben ist, z.
B. wenn in einem Accept() Aufruf sich ein client verbunden hat. Ich habe
leider Dein Neuverbinden-Beispiel nicht gefunden, könntest Du mir mal
bitte die URL geben? Doch ich habe Dein TCPClientServer Beispiel mal
getestet, Du hast da Client und Server als mehrere Startprojekte
definiert, wenn man nur den Server startet blockiert natürlich die
Anwendung, und zwar hier:
socket = tcpListener.AcceptSocket(); // i am a blocking method
Da wird so lange blockiert bis sich ein client verbindet, auch wenn der
Aufruf in einer Schleife wäre. Klar dass das nicht bemerkt wird wenn der
client gleich mitgestartet wird und sich natürlich sofort verbindet doch
spätestens dann blockiert Dein server wieder und zwar hier:
received = socket.Receive(buffer);
So lange der client keine Daten schickt kehrt die Receive() Methode
nicht zurück, das kann man leicht testen wenn man auf "Debuggen" + "Alle
unterbrechen" geht. Der Grund für die Schleife ist ja dass eben quasi
endlos vom socket gelesen wird, aber das blockieren bleibt.
An der Stelle müsste man einen thread erzeugen der ständig einen Poll()
macht und wenn der Poll feststellt dass etwa neue Daten da sind, dann
würde man Receive() aufrufen und würde eben nicht blockieren weil ja
schon durch den Poll() festgestellt wurde dass Daten da sind. Nach
starten dieses Poll-threads wäre die Anwendung wieder frei und würde
nirgendwo blockieren.
>>> Man führt letztlich - ob synchron oder asynchron - eine Schleife aus,
>>> die ständig eine Aktion auf
>>> dem Socket oder TcpClient ausführt, aus.
>>
>> Mache ich nicht so, ich bevorzuge die asynchronen Funktionen.
>
> Intern führen die quasi immer eine Schleife aus.
> Es ist dadurch die gleiche Systematik.
Nein, Receive() führt keine Schleife aus. BeginReceive(), die asynchrone
Variante richtet einen thread ein und startet eine Schleife. Wird etwas
empfangen dann wird die parametrierte CallBack-Methode aufgerufen die
dann nach dem auslesen der Daten EndReceive() aufruft. Letztere beendet
den mit StartReceive() eingeleiteten asynchronen Vorgang, beendet den
thread und gibt resourcen frei. Üblicherweise wird dann aber erneut ein
asynchroner Receive angestoßen so daß immer ein receive pending ist. Ist
ja auch in den Microsoft Beispielen für die asynchronen socket Methoden
so beschrieben. Auch wird üblicherweise ein asynchroner Accept() d. h.
BeginAccept() immer wieder angestossen denn man will ja dass sich
mehrere clients zum server verbinden können.
>>> Oder wo ein Socket.Poll ausgeführt wird:
>>>
>>> [Socket.Poll-Methode (System.Net.Sockets)]
>>> http://msdn.microsoft.com/de-de/library/system.net.sockets.socket.poll.aspx
>>>
>>
>> Der Aufruf der asynchronen Funktion wie etwa read/rcv erspart es einem
>> ja einen eigenen Poll-Mechanismus zu implementieren.
>
> Asynchron erspart einem gar nichts. Im Gegenteil,
> es ist wesentlich komplizierter.
Na das ist Ansichtssache, was sollte denn der Grund für die
Implementierung der asynchronen socket Methoden sein wenn nicht die
vollständige Kapselung des Einrichten eines threads und einer
Poll-Schleife? Also der Sinn ist doch dass blockierende Methoden für den
Entwickler entfallen können, war ja schon bei WSAAsyncSelect() so.
> Intern findet in so einer Lösung immer ein Pollen
> statt, um eine Connection zu beobachten,
> da ist vollkommen egal ob asynchron oder synchron.
Was meinst Du mit "intern"? Den code der Receive() Methode? Ich gehe
jede Wette ein dass da weder ein thread erzeugt wird noch eine Schleife
ausgeführt wird doch selbst wenn, ist und bleibt die Methode
blockierend. Das was Du mit Pollen meinst muss natürlich selbst
implementiert werden deshalb gibt es ja eine Poll() Methode und diese
blockiert natürlich nicht, muss aber ständig aufgerufen werden und
sollte in einem eigenen thread eingebettet sein.
Noch eine Bemerkung zu Deinem TcpClientServer Beispiel:
Ist zwar ganz nett doch Du benutzt blockierende Methoden, ist für eine
Power-Anwendung weniger geeignet da die GUI einfriert.
Der Server kann nur einen Client verbinden, wäre etwa ungeeignet für
einen Power-server (web-server).
> ciao Frank
Gruß,
Peter
> > Es blockiert nicht, wenn das in einer Schleife gemacht wird,
> > das ist recht einfach in meinem "Neuverbinden"-Beispiel
> > auf meiner Webseite zu sehen.
>
> Nein, eine blockierende Funktion blockiert auch in einer Schleife,
nein, schau Dir einfach mein Beispiel an, dann siehst
Du, dass die da nichts blockiert Peter. Man, ist aber
auch schwer mit Dir.
> weniger geeignet da die GUI einfriert.
Quark, die friert nicht ein. Nicht in meinem download-
baren Beispiel, und auch nicht in anderen Szenarien.
Liegt wohl alles an Deinem Missverständnis, da
würde was blockieren.
Ich mach mal ein EOT.
[Bearbeiten von Steuerelementen aus Threads]
http://dzaebel.net/ControlInvoke.htm
Ein Thread (mit IsBackground=true;)
blockiert nicht die GUI.
Der Server ist bei mir eh nur ein Beispiel.
Server laufen eher später im Hintergrund oder
als Dienst. Blockieren heisst ja auch nicht
"nicht funktionieren", im Server-Szenario
ja eher als Wartezustand zu kennzeichnen,
den man nicht unnütz durch asynchrones
Handling aufbläht / verkompliziert (nur bei Bedarf).
Trotzdem, ein EOT.
Ich gehe mit Dir jede Wette ein dass das Blockierverhalten einer
blockierenden Funktion nicht davon abhängt ob sich der Aufrufer
in einer Schleife befindet.
> nein, schau Dir einfach mein Beispiel an, dann siehst
> Du, dass die da nichts blockiert Peter. Man, ist aber
> auch schwer mit Dir.
Moment mal, hatte geschrieben dass ich Dein "Neuverbinden"-Beispiel
nicht gefunden habe und Dich um die URL gebeten, sonst kann ich das
ja nicht nachvollziehen. Doch ich hatte ganz deutlich von Deinem
Sample-Code TcpClientServer geredet, den habe ich runtergeladen und
getestet und der blockiert sehr wohl im Accept() und auch im Receive(),
Accept() dann wenn wie schon gesagt der Client nicht mitgestartet wird.
Probier es doch mal aus, wenn Du dann auf Debug unterbrechen gehst
steht der cursor an der Position der blockierenden Funktion die eben
noch nicht zurückgekehrt ist.
>> weniger geeignet da die GUI einfriert.
>
> Quark, die friert nicht ein. Nicht in meinem download-
> baren Beispiel, und auch nicht in anderen Szenarien.
> Liegt wohl alles an Deinem Missverständnis, da
> würde was blockieren.
Es liegt in der Natur der Dinge dass ein Server sich nicht sicher sein
kann wann oder ob überhaupt sich ein Client verbindet, das kannst Du
doch nicht im Ernst abstreiten? Da Accept() den socket zum kommunizieren
mit dem client als Rückgabewert liefert, muss ja diese Funktion so lange
blockieren bis sich ein Client verbindet. Dass Accept() eine
blockierende Funktion ist sollte bekannt sein. Wenn Accept() dann
innerhalb des FormLoad events aufgrufen wird friert die GUI ein, dass
man überhaupt das Formular sieht liegt am Show() ganz am Anfang.
Bau einfach mal ein Menü in Dein Formular ein und versuche da etwas
auszuwählen solange Du von LoadForm aus eine Funktion aufgerufen hast
die noch nicht zurückgekehrt ist. Das möchte ich mal sehen.
> Ich mach mal ein EOT.
Ok. Danke für die Diskussion.
> ciao Frank
> --
> Dipl.Inf. Frank Dzaebel [MCP/MVP C#]
> http://Dzaebel.NET
Gruß,
Peter
Sagte ich ja bereits, erst hast Du es aber verneint.
> aber das muss
> ja nicht so sein. Siehe da ggf.
>
> [Bearbeiten von Steuerelementen aus Threads]
> http://dzaebel.net/ControlInvoke.htm
Hat mit Invoke hier nichts zu tun, der Server blockiert weil Du in dem
LoadForm event eine blockierende Funktion aufrufst. Teste doch mal den
Server an ohne den Client zu starten, habe es vorhin nochmals probiert,
dann kommt in der Title Bar "Keine Rückmeldung ....". Außerdem ständig
Sanduhr. Habe ein Menü eingebaut, kann nicht aufgerufen werden. Sogar
wenn ich auf "Nächste Anweisung festlegen" gehe und den bereits
aufgerufenen Accept() beenden möchte kommt eine Fehlermeldung. Ich rede
hier von dem TcpClientServer Beispielcode.
Ich sage das hier nicht um irgendeinen Beispielcode schlecht zu machen,
also bitte nicht falsch verstehen. Ich finde es super dass Du so viele
Beispiele auf Deiner website anbietest.
> Ein Thread (mit IsBackground=true;)
> blockiert nicht die GUI.
Natürlich nicht, aber wie soll eine GUI die aus einem Formular besteht
gscheit funktionieren wenn die zugrundeliegende Form noch nicht mal
ihren LoadForm event beendet hat weil dort ein blockierender
Funktionsaufruf eben diese Beendigung verhindert. Die Applikation friert
ein, ist doch klar.
> Der Server ist bei mir eh nur ein Beispiel.
> Server laufen eher später im Hintergrund oder
> als Dienst. Blockieren heisst ja auch nicht
> "nicht funktionieren", im Server-Szenario
> ja eher als Wartezustand zu kennzeichnen,
> den man nicht unnütz durch asynchrones
> Handling aufbläht / verkompliziert (nur bei Bedarf).
Natürlich heißt blockieren nicht automatisch nicht funktionieren, das
habe ich auch nie behauptet, im Gegenteil hatte ich die asynchronen
Funktionen angesprochen die ja eben nicht blockieren. Und eine GUI kann
bei einem Dienst nie blockieren denn ein Dienst hat selbst keine GUI,
das ist wohl wahr. Doch ein Client hat oft eine GUI (z. B. browser) und
auch ein client sollte nicht im FormLoad event blockierde Funktionen
aufrufen.
> Trotzdem, ein EOT.
Du solltest Dich mal wirklich mit den asynchronen socket Funktionen
anfreunden, die sind so kompliziert gar nicht.
> ciao Frank
> --
> Dipl.Inf. Frank Dzaebel [MCP/MVP C#]
> http://Dzaebel.NET
Gruß,
Peter
Leider blockt jetzt nicht nur dein Accept() und dein Receive() sondern
auch du selbst. Dabei kann man in jedem Buch nachlesen dass das
blockierende Funktionen sind.
EOT = Ego Ohne Teamfähigkeit?
Gruß,
Peter
> nein, schau Dir einfach mein Beispiel an, dann siehst
> Du, dass die da nichts blockiert Peter. Man, ist aber
> auch schwer mit Dir.
Habe es nicht nur angeschaut sondern runtergeladen, installiert und
ausgeführt. Die GUI hat blockiert, woran das liegt sagte ich bereits.
Dann ist es sogar abgeschmiert (keine Rückmeldung...) und es wurde eine
Fehlermeldung an Microsoft geschickt.
An dieser Stelle würde mich interessieren was andere für Erfahrungen mit
den Beispielen gemacht haben. Danke im Voraus.
Gruß,
Peter
Hallo Peter,
über das EOT von Frank darfst du dich nicht ärgern. Hat er mit mir und
anderen auch so gemacht, und zwar grundsätzlich dann, wenn er mal einen
Fehler gemacht hat. Trotzdem - Frank ist jemand, der noch mit am meisten
weiß, und definitiv am meisten Zeit in die NG einbringt. Von daher ist das
zwar schade, stört mich jetzt aber nicht weiter.
Greetz
Paule
Hi Paule,
tausend Dank für Deinen Beitrag, hat mir sehr geholfen das ganze besser
zu verstehen. Mir ist absolut klar dass Frank sehr vielen usern hier
hilft und auch auf seiner website sehr viel an tipps & tricks sowie
Beispielcode anbietet. Sein Focus ist - so wie ich das einschätze - auch
jemand eben schnell zu helfen, auch wenn es oftmals nur weiterführende
links sind.
Dennoch braucht er ja nicht gleich sauer zu sein nur deswegen weil ihm
jemand mitteilt dass seine Minimalanwendung mit dem blockierenden Socket
Aufruf innerhalb der LoadForm() methode blockiert wenn man den client
nicht mitstartet. Das soll ja auch nur eine Beispielanwendung sein denke
ich was er ja später auch bestätigt hat bzw. schrieb er dass man so
einen Server sowieso als service implementieren würde etc. etc. Doch
Accept() ist halt eine blockierende Socket-Funktion und blockiert die
aufrufende Funktion so lange bis eben Accept() zurückkehrt mit dem
Verbindungssocket. Mag vielleicht sein dass das Frank nicht sonderlich
interessiert, aber es ist doch nicht o. k. wenn man Falsches hier
schreibt, denn andere, mit sockets ungeübte user, könnten das ja glauben
und das wäre ihnen keine Hilfe beim Schreiben einer Applikation mit
sockets.
Mir könnte es im Grunde egal sein, ich habe ja auch nur versucht
Christian zu helfen der Probleme hatte. Ich habe seit 1999 Erfahrungen
in der socket Programmierung, unter UNIX, unter Windows, als GUI und als
NT Service, mit C# auch. Habe etwa Server für eine finnische Firma
geschrieben welche AGVs Fahraufträge geben, oder Roboter-Kommunikation
zwischen PLC und Open-Ingres inclusive Inbetriebnahme in Taiwan.
Deswegen weiß ich auch was man da alles falsch machen kann, das was ich
da vorgefunden hatte war ein Chaos! Die hatten pro Telegrammtyp einen
eigenen Server der jeweils in einem eigenen Prozess lief. Warum wohl?
Weil eben Accept() blockiert. Der Code ALLER Server unterschied sich nur
durch den listening port und den Telegramm-Handler, der restliche code
war bei allen Servern identisch! Das wäre wie wenn man etwa für jede
statische html-Seite einen eigene webserver bräuchte.
Jedenfalls finde ich dass man sich in einem Forum schon austauschen
sollte und nicht nur auf Beispiele oder Links hinweisen sondern grade
auch das persönliche know-how einbringen sollte.
Gruß,
Peter
> Frank ist jemand, der noch mit am meisten weiß,
oh, vielen Dank, da möchte ich aber sagen: ... *alle*
geben hier Ihren Beitrag und *zusammen* tauschen wir
Erfahrungen aus / können *unsere* Erkenntnisse maximieren.
> ... er mal einen Fehler gemacht hat ...
ich mache öfters Fehler, aber hier nicht.
Peter hat wahrscheinlich jahrenlang nur
asynchron programmiert und ihm ist der Blick
für das Synchrone etwas entfallen.
Insbesondere denkt er, synchrones
TcpClient-Handling würde das UI blockieren/einfrieren.
Das ist aber unrichtig und hat eigentlich gar nichts
miteinander zu tun und es gibt auf meiner Webseite auch
genügend Beispiele dazu, auch Du weisst das sicher.
Das eine ist Threading, das andere sind Sockets/TcpClient,
das bekommt er hier durcheinander.
Aber lasset uns hier Gespräche über dritte vermeiden, das
ist generell schlechter Stil. Redet bitte eher technisch,
(nicht persönlich) denn das technische C# ist das Thema der
Gruppe und hilft auch später anderen.
BTW: ein EOT ist von jedem hier zu respektieren.
Das ist zwar jetzt OT: Wie kommt Du zu dieser Annahme? Damit wäre jede noch
so falsche Aussage unangreifbar, wenn der Autor ein "EOT" postet und damit
die Diskussion abwürgt. "EOT" ist einfach nutzlos, man sollte es vermeiden.
Wenn man nichts mehr sagen will oder nichts zu sagen hat, braucht man ja
nicht zu antworten.
--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://dotnet.mvps.org/dotnet/faqs/>
> Hallo Peter,
>
> über das EOT von Frank darfst du dich nicht ärgern.
Nochmals Danke für den Tipp. Doch den Thread hatte Christian Bayer mit
einer Frage eröffnet, eigentlich sollte Christian das EOT setzen.
> Hat er mit mir und
> anderen auch so gemacht, und zwar grundsätzlich dann, wenn er mal einen
> Fehler gemacht hat.
Einen Fehler zu machen ist ja nicht schlimm, doch einen Fehler nicht zu
erkennen oder diesen gar zu vertuschen steht auf einem anderen Blatt.
Doch dieser, Dein Satz hat's in sich.
Zurück zum Thema Sockets:
Meine Absicht war Christian mit seiner Socket-Anwendung zu helfen, so
bin ich auf den Beispielcode http://dzaebel.net/TcpClientServer.htm
gestossen und habe diesen ausprobiert. Zum Verhalten habe ich dann
einiges gepostet und vorhin habe ich es erneut getestet. Jetzt möchte
ich mal Dich Paule oder andere user bitten dieses Projekt
herunterzuladen, im Projektmappen-Explorer die top-node auszuwählen (die
Projektmappe) und dann die Eigenschaftenseiten (Shift+F4) aufzurufen und
dann unter "Mehrere Startprojekte" auszuwählen dass nur der Server
gestartet wird, also den Client bei "Aktion" auf "Keine" setzen. Wenn
wir schon über synchron/asynchron reden dann sollten wir uns schon
darauf einigen, dass ein Server nicht weiß wann sich ein Client
verbindet. Oder müssen wir etwa jedesmal beim Server-Betreiber per
Telefon anrufen dass man den Webserver starten soll da man sich als
Client mit einem Browser verbinden will? Also mal im Ernst, nichts ist
asynchroner als das Internet und wir reden hier über stream-sockets
(TCP-Protokoll) und ihre Funktionsweise in Anwendungen.
Wenn Du Paule oder auch andere user also mal Zeit hätten das selbst
auszuprobieren was da passiert wenn just die Server-Anwendung mit der
von "Form" abgeleiteten Klasse "Server.cs" gestartet wird, dann könnten
sich tatsächlich wie Frank meint *unsere* Kenntnisse erweitern,
maximieren erwarte ich gar nicht. Danke.
Gruß,
Peter
> > BTW: ein EOT ist von jedem hier zu respektieren.
>
> Das ist zwar jetzt OT: Wie kommt Du zu dieser Annahme?
Ja, ist auch wieder OT, und das kann man gut in
anderen Gruppen besprechen.
Der Grund ist natürlich, weil das *seine* Entscheidung
ist. Es ist immer ein Entgegenkommen desjenigen, wenn
er postet. Es ist vollkommen frei, ob jemand postet.
Es gibt hier keinen Zwang.
> "EOT" ist einfach nutzlos, man sollte es vermeiden.
EOT ist in mehreren Situationen sinnvoll.
Meistens ist ja auch ein Begründung dabei,
aber häufig auch durch den Verlauf ersichtlich.
Ich erinnere mich an Eskapaden, wo z.B.
einige bis 100 Postings in einem Thread
hatten. Da waren Anfeindungen bis zum
"Geht nicht mehr" drin. Sowas hätte man
evtl. relativ früh mit
einem EOT stoppen können. Oft kann man
Meinungen einfach so stehen lassen und
muss nicht weiter versuchen seine Auffassung
durchzu"drücken". Ich mache da gerne ein EOT,
denn Flamewars bringen vielleicht was für das
Amüsement, für mich eher jemand technisch
interessierten (und das ist das Thema dieser Gruppe)
ist das vermeidbar.
> Wenn man nichts mehr sagen will oder nichts zu
> sagen hat, braucht man ja nicht zu antworten.
Finde ich eher unsauber. Die Information, dass
der Poster (bewusst) entschieden hat - aus was
für einem Grund auch immer - nicht mehr zu diesem
Thema zu posten, hilft (dem) anderen, denn
er weiss, dass derjenige es nicht mehr möchte
und erwartet (normal) auch nichts mehr.
Bitte solche Dinge in anderen Foren diskutieren.
Das MVP Forum zum Beispiel, da kannst Du
eine Frage/Info hineinstellen.
Danke Herfried für Dein Posting, Deiner Meinung möchte ich mich
anschliessen. Zumal hier auch der thread gar nicht von FZ eröffnet wurde
sondern von einem Christian Bayer. Er hat offensichtlich ein Problem
dass sein client "disconnects" nicht erkennt. Mein C# client kann das
aber, habe es gestern erst nochmals getestet. Ein POP3-login bei meinem
provider, dann ein USER und PASS gesendet, dann ein UIDL und dann
einfach idle gewesen. Nach 10 Minuten beendete der POP3-server die von
meinem C# client initiierte Verbindung und zwar natürlich ohne dass ich
da ständig Daten an den POP3-server senden musste (was auch, NOP
commands? wozu?) was laut FZ offenbar nötig wäre.
Doch Christian hat wohl sein Problem schon gelöst, jedenfalls hat er
sich für meinen code nicht interessiert, hat ja auch nichts mehr von
sich hören lassen.
Gruß,
Peter
Jetzt ist es nun mal Thema.
>Der Grund ist natürlich, weil das *seine* Entscheidung
>ist. Es ist immer ein Entgegenkommen desjenigen, wenn
>er postet. Es ist vollkommen frei, ob jemand postet.
>Es gibt hier keinen Zwang.
Genausowenig gibt es einen Verbot der Diskussion dadurch, daß jemand "EOT"
schreibt. Und das ist auch schon der Knackpunkt: Welchen Zweck soll es dann
haben, außer darauf hinzuweisen, daß man sich ausklinkt (was man genausogut
"sanfter" tun könnte, indem man einfach nicht antwortet)?
> "EOT" ist einfach nutzlos, man sollte es vermeiden.
>EOT ist in mehreren Situationen sinnvoll.
>Meistens ist ja auch ein Begründung dabei,
>aber häufig auch durch den Verlauf ersichtlich.
>Ich erinnere mich an Eskapaden, wo z.B.
>einige bis 100 Postings in einem Thread
>hatten. Da waren Anfeindungen bis zum
>"Geht nicht mehr" drin. Sowas hätte man
>evtl. relativ früh mit
>einem EOT stoppen können.
Eskapaden stoppt man am Besten, indem man sachlich bleibt (also keine
Kompetenzbewertungen), tolerant gegenüber anderen Ansichten ist (Toleranz
bedeutet nicht, daß man andere Ansichten teilt) oder sich einfach
zurückhält. Da braucht es keinen Moderator, Richter oder Polizisten, der
Diskussionen mit "EOT" für beendet erklärt oder konstatiert, daß eine
Diskussion "unsachlich" sei.
>> Wenn man nichts mehr sagen will oder nichts zu
>> sagen hat, braucht man ja nicht zu antworten.
>
>Finde ich eher unsauber. Die Information, dass
>der Poster (bewusst) entschieden hat - aus was
>für einem Grund auch immer - nicht mehr zu diesem
>Thema zu posten, hilft (dem) anderen, denn
>er weiss, dass derjenige es nicht mehr möchte
>und erwartet (normal) auch nichts mehr.
Ich halte Diskussionsverweigerung trotz offener Punkte für nicht besonders
diskursfördernd und lösungsorientiert, ungeachtet dessen, ob man sich
stillschweigend ausklinkt oder "EOT" schreibt. In diesem Fall interpretiere
ich "EOT" eher als Provokation, als bewußten Versuch eines
Diskussionsteilnehmers, eine fachliche Diskussion auf der Metaebene
abzuwürgen. So gesehen ist sogar ein "EOT" bereits unsachlich, da es den
technischen Diskurs verläßt.
>Das MVP Forum zum Beispiel, da kannst Du
>eine Frage/Info hineinstellen.
Ich habe weder Frage noch "Info", sondern schreibe nur, was ich denke, genau
so, wie Du es getan hast.
Eigentlich wollte ich just Christian mit seinem Problem helfen, socket
Programmierung in C#. Das war doch das Thema, oder?
>> "EOT" ist einfach nutzlos, man sollte es vermeiden.
>
> EOT ist in mehreren Situationen sinnvoll.
> Meistens ist ja auch ein Begründung dabei,
> aber häufig auch durch den Verlauf ersichtlich.
> Ich erinnere mich an Eskapaden, wo z.B.
> einige bis 100 Postings in einem Thread
> hatten. Da waren Anfeindungen bis zum
> "Geht nicht mehr" drin.
Wo bitte habe ich hier Anfeindungen iniziiert? Das läge mir aber auch so
etwas von fern, ich wollte hier meine Erfahrungen bezüglich Socket
Programmierung austauschen bzw. helfen.
> Sowas hätte man
> evtl. relativ früh mit
> einem EOT stoppen können. Oft kann man
> Meinungen einfach so stehen lassen und
> muss nicht weiter versuchen seine Auffassung
> durchzu"drücken". Ich mache da gerne ein EOT,
> denn Flamewars bringen vielleicht was für das
> Amüsement, für mich eher jemand technisch
> interessierten (und das ist das Thema dieser Gruppe)
> ist das vermeidbar.
Du hattest geschrieben:
> oh, vielen Dank, da möchte ich aber sagen: ... *alle*
> geben hier Ihren Beitrag und *zusammen* tauschen wir
> Erfahrungen aus / können *unsere* Erkenntnisse maximieren.
Wie soll das gehen wenn technische Zusammenhänge falsch dargestellt
werden und einfach nicht stimmen? Kann man mit einem EOT die
Erkenntnisse etwa maximieren?
Meine Socket-Anwendungen (UNIX und Windows Plattform) laufen in rauhen
industriellen Umgebungen, da werden Roboter bewegt und etwa Filaments
produziert, rund um die Uhr. Die bestehen nicht nur aus einer Form mit
einer TextBox. Du sagst Du wärst technisch interessiert und würgst
dennoch eine Diskussion um ein nicht gerade triviales Thema der Socket
Programmierung dennoch ab, als wenn alles geklärt wäre.
>> Wenn man nichts mehr sagen will oder nichts zu
>> sagen hat, braucht man ja nicht zu antworten.
>
> Finde ich eher unsauber. Die Information, dass
> der Poster (bewusst) entschieden hat - aus was
> für einem Grund auch immer - nicht mehr zu diesem
> Thema zu posten, hilft (dem) anderen, denn
> er weiss, dass derjenige es nicht mehr möchte
> und erwartet (normal) auch nichts mehr.
Du verwechselst mich da mit Christian, er hatte den Thread mit seiner
Frage bzw. seinem Problem gestartet, nicht ich. Wieso dann ausgerechnet
Du den thread beenden willst ist mir unverständlich.
> ...idle gewesen. Nach 10 Minuten beendete der POP3-server die von meinem
> C# client initiierte Verbindung
dies ist ein _ordentlicher_ shutdown/close,
(vereinfacht zB: Server sendet 'FIN' segment an den Client)
danach wird die Session (beidseits) selbstverständlich richtig/sofort/sauber
beendet...
> ohne dass ich da ständig Daten an den POP3-server senden musste
solches ist nur nötig,
wenn man einen fatalen _Verbindungs-Unterbruch_
baldmöglichst erkennen will/muss!
Also wenn in deinem Bsp direkt beim POP3-Server
das Netzwerkkabel ausgezogen würde,
dann bekommt dein Client wohl nie ein sauberes shutdown/close (FIN).
[Achtung: ggf Firewalls oä hier mal ausgenommen]
Die Session bleibt in deinem Client dann enorm lange/ewig 'offen',
es gibt auch keine Exception, Read=0 oder sonstwas.
[Achtung: Netzwerkkabel lokal ausziehen ist ein anderer Fall]
--
Thomas Scheidegger - 'NETMaster'
http://dnetmaster.net/
Erneuten Dank für Deinen Beitrag Herfried, möchte mich Deiner Meinung
anschliessen.
Gruß,
Peter
Da es Dir *sehr* wichtig scheint, weiter das
Thema mit den (synchronen) Sockets zu verstehen,
werde ich nochmal versuchen es weiter zu erklären,
Thomas hat sich ja auch eingeschaltet.
Ich habe aufgehört, weil ich da keine Fortschritt sah
und sowas kenne, es führt zu nichts - glaubs mir, ein
EOT war da schon am geeignetsten, ich kenne das
hier schon ziemlich lange ;-).
Ein EOT solltest Du normal respektieren!
Aber gut, Du hast deutlich gemacht,
wie sehr Dir das technische am Herzen liegt und
bei so viel Interesse ist ja ggf. auch wieder
fruchtbares Gespräch möglich.
> den Beispielcode http://dzaebel.net/TcpClientServer.htm
> gestossen und habe diesen ausprobiert.
Es sind ja mehrere Downloads da. In meiner Seite stand
aber schon immer, das es nur ein einfaches Beispiel ist.
Die Beispiele sind aufgrund von Fragen von anderen
Usern gekommen. Zum Beispiel ist einmal der Server
auch UI-blockierend. Das heisst aber nicht,
dass "synchrone Sockets" und UI-Blockierung
sich bedingen würden.
Zum Beispiel ist im 4ten Download
[Download .NET 2.0 Server nicht UI-blockierend.]
ein Beispiel, wo der Server nicht blockiert.
Das eine ist das Thema "Threading" das andere ist
das Gebiet der "Sockets/TcpClient" - zwei Paar Schuhe.
Wenn irgendwas in meinen Downloads nicht klappt,
kannst Du gerne hier einen Hinweis/Vorschlag geben,
dann korrigiere ich das, wenn das als wichtig
erachtet wird (und ich Zeit habe ;-)
Nimm Dir ruhig die Zeit und antworte nach
eingehender Prüfung.
> Hallo Peter
Hallo Thomas
>
>> ...idle gewesen. Nach 10 Minuten beendete der POP3-server die von
>> meinem C# client initiierte Verbindung
>
> dies ist ein _ordentlicher_ shutdown/close,
> (vereinfacht zB: Server sendet 'FIN' segment an den Client)
> danach wird die Session (beidseits) selbstverständlich
> richtig/sofort/sauber beendet...
Ja, wird auch manchmal als "graceful" bezeichnet. Dass mein POP3-Client
aber überhaupt idle werden kann liegt daran, dass ich einen interaktiven
Modus habe bei welchem man die POP3 Befehle manuell eingeben kann.
>> ohne dass ich da ständig Daten an den POP3-server senden musste
>
> solches ist nur nötig,
> wenn man einen fatalen _Verbindungs-Unterbruch_
> baldmöglichst erkennen will/muss!
Ok, hört sich vernünftig an. Wenn ich in diesem Falle den Server selbst
schreibe kann ich natürlich auch einen "NOP" implementieren oder eine
sonstige keep-alive Funktion, aber wenn es ein Server ist auf welchen
ich keinen Einfluß habe, was für Daten/Kommandos soll man denn da
schicken um zu prüfen on die Verbindung nicht mehr steht?
> Also wenn in deinem Bsp direkt beim POP3-Server
> das Netzwerkkabel ausgezogen würde,
> dann bekommt dein Client wohl nie ein sauberes shutdown/close (FIN).
> [Achtung: ggf Firewalls oä hier mal ausgenommen]
> Die Session bleibt in deinem Client dann enorm lange/ewig 'offen',
> es gibt auch keine Exception, Read=0 oder sonstwas.
> [Achtung: Netzwerkkabel lokal ausziehen ist ein anderer Fall]
Ja, da hast Du absolut Recht. Doch bei meinem POP3-Client ist es eh der
Client der, nachdem mails bzw. mail-headers geholt wurden, die
Verbindung durch senden von QUIT einleitet. In meinem Auto-Mode läuft
die komplette Sequenz ab um entweder mails oder nur die header zu holen,
der Client ist also der Teilnehmer der aktiv Befehle sendet und auf
jeden POP3-Befehl muss der client natürlich auf korrekten response des
Servers prüfen (+OK bzw. -ERR), auch kriegt jeder gesendete Befehl einen
timout bez. des response vom Server. Würde dieser sich also "ungraceful"
verabschieden würde sich die eingeleitete session eh beenden, da dann
auf den letzten gesendeten POP3-Befehl das timeout greift.
Danke für Dein posting,
Peter
>
> Ich habe aufgehört, weil ich da keine Fortschritt sah
> und sowas kenne, es führt zu nichts - glaubs mir, ein
> EOT war da schon am geeignetsten, ich kenne das
> hier schon ziemlich lange ;-).
> Ein EOT solltest Du normal respektieren!
Frank,
normalerweise ist ein EOT sinnvoll, wenn keine weiteren Ergebnisse zu
erwarten sind. In dem Fall, um den es hier geht, ist dies aber nicht so. Im
Gegenteil: Wenn dein Programm bei jemandem blockiert, bei dir aber nicht
(?), so liegt hier irgendwo etwas vor, was man ans Licht bringen sollte.
Gerade zu diesen Dingen sind die NGs eigentlich da - tieferes Wissen
öffentlich zu machen, das aus Dokus nicht hervorgeht. Und genau genommen
lohnt es sich auch nur in solchen Fällen, eine Diskussion überhaupt zu
führen. IMO ist gerade hier also ein EOT vollkommen fehl am Platze.
Du wirst dich an den Druckerthread erinnern: Ich konnte deine Frage bzgl.
bestimmter Properties von Winforms nicht beantworten, weil ich in der
Anwendung keine Winforms habe. Ich finde es gelinde gesagt arrogant, dann
einfach mit "warum beantowetest du die Frage nicht" ein EOT zu deklarieren.
Gerade auch hier gibt es wohl offensichtlich große Verständnisunterschiede,
was Drucken angeht, deren Diskussion sicherlich das Verständnis aller über
das Thema verbessern könnten. Dazu sehe ich die NG als das Mittel der Wahl.
Grüße
Paule
> Bedeutung von EOT.
Schon wieder "off topic".
Ich habe meine Meinung dazu schon kund getan.
Mehr ist normal nicht zu sagen, es gibt viele
Szenarien, in denen EOT sinnvoll ist. Wenn
ich Sie Dir mal erklären soll, kann Du mich
gern privat anschreiben, dann kann ich Dir das
mal erläutern.
Dieses hier ist eine C# Gruppe hier sprechen
wir über C# Themen.
__________________
EOT heisst übrigens nur, dass man sich
nicht mehr weiter zu einem Thema äussern
möchte. So übrigens auch zu diesem hier ;-)
Es gibt mehrere Definitionen - einige
interpretieren es auch als Angebot
des Beendens des (ggf. fruchtlosen) Themas.
Andere können aber natürlich munter weiterdiskutieren.
Man selber entscheidet sich dafür, es nicht zu tun.
Dies gibt man auch noch bekannt, sodass andere
wissen, dass nichts mehr von demjenigen zum
Thema kommt.
Das ist auch nicht unbedingt bös gemeint, häufig
eher Community schonend (Verhindern von Flamewars).
Oft ist ja auch so, dass andere noch nach
einem EOT noch übelst nachhaken - wohl wissend,
dass derjenige ja nicht mehr antworten möchte/wird.
*Respektvoll* ist da, soetwas nicht zu tun.
Ich werde mich jetzt nicht weiter zum Thema
EOT äussern, denn es ist off topic und von meiner
Seite ist alles gesagt.
Wir haben hier ein ganz anderes Thema und halte
Dich bitte an die Standard-Newsgroup-Nettiwuette:
- "nur Postings zum jeweiligen Thema"
- "in den Microsoft-Newsgroups geht es außerdem um
rein fachlichen Erfahrungs- und Wissensaustausch."
[Newsgroup - Netikette]
http://support.microsoft.com/gp/ngnetikette/de
Es geht in diesem Thread um Socket-Verbindungen ;-)
Da es Dir *sehr* wichtig scheint, weiter das
Thema mit den (synchronen) Sockets zu verstehen,
werde ich nochmal versuchen es weiter zu erklären,
Thomas hat sich ja auch eingeschaltet.
Ich habe aufgehört, weil ich da keine Fortschritt sah
und sowas kenne, es führt zu nichts - glaubs mir, ein
EOT war da schon am geeignetsten, ich kenne das
hier schon ziemlich lange ;-).
Ein EOT solltest Du normal respektieren!
Aber gut, Du hast deutlich gemacht,
wie sehr Dir das technische am Herzen liegt und
bei so viel Interesse ist ja ggf. auch wieder
fruchtbares Gespräch möglich.
> den Beispielcode http://dzaebel.net/TcpClientServer.htm
> gestossen und habe diesen ausprobiert.
Es sind ja mehrere Downloads da. In meiner Seite stand
aber schon immer, das es nur ein einfaches Beispiel ist.
Die Beispiele sind aufgrund von Fragen von anderen
Usern gekommen. Zum Beispiel ist einmal der Server
auch UI-blockierend. Das heisst aber nicht,
dass "synchrone Sockets" und UI-Blockierung
sich bedingen würden.
Zum Beispiel ist im 4ten Download
[Download .NET 2.0 Server nicht UI-blockierend.]
ein Beispiel, wo der Server nicht blockiert.
Das eine ist das Thema "Threading" das andere ist
das Gebiet der "Sockets/TcpClient" - zwei Paar Schuhe.
Wenn irgendwas in meinen Downloads nicht klappt,
kannst Du gerne hier einen Hinweis/Vorschlag geben,
dann korrigiere ich das, wenn das als wichtig
erachtet wird (und ich Zeit habe ;-)
Nimm Dir ruhig die Zeit und antworte nach
eingehender Prüfung.
Danke Paul, das sehe ich genauso. Letztens schrieb ja Frank, Zitat: "Zum
Beispiel ist einmal der Server auch UI-blockierend". Ich habe in meinen
postings genau gesagt dass ich das Beispiel
"http://dzaebel.net/TcpClientServer.htm " meine, und dass dort die GUI
einfriert, habe auch erklärt warum (Accept innerhalb LoadForm). Kurz
danach kam das EOT. Mehrfach habe ich betont dass ich dieses Beispiel
nicht kritisiere, ich habe lediglich das Verhalten erklärt und dass das
so ist wenn man den zugehörigen Client eben nicht mitstartet. Ich
verstehe immer noch nicht was mir Frank eigentlich über blockierende
Socket-Funktionen Neues beibringen möchte, ich habe den thread gar nicht
betreten weil ich Hilfe diesbezüglich brauche, im Gegenteil, ich wollte
lediglich Christian helfen dem ich empfohlen habe zumindest einen
"graceful" disconnect mitzubekommen, indem er ständig einen Read/Rcv
pending hält.
> Gerade zu diesen Dingen sind die NGs eigentlich da - tieferes Wissen
> öffentlich zu machen, das aus Dokus nicht hervorgeht.
Dem kann ich nur zustimmen, also wenn ich selbst mal eine Frage habe ist
es durchaus okay wenn mir jemand hilft indem ich einen Link zu einem
Artikel oder Samplecode erhalte, wenn mir aber ein NG-Mitglied
Zusammenhänge selbst erklären kann, dann bevorzuge ich diese
Wissensvertiefung durch direkten Erfahrungsaustausch.
> Und genau genommen
> lohnt es sich auch nur in solchen Fällen, eine Diskussion überhaupt zu
> führen. IMO ist gerade hier also ein EOT vollkommen fehl am Platze.
Vollkommen richtig, das seh ich auch so und bin froh darüber dass ich
mit dieser Meinung nicht alleine bin, Herfried hat sich ja ähnlich geäußert.
> Du wirst dich an den Druckerthread erinnern: Ich konnte deine Frage bzgl.
> ---8<---snip------8<---snip------8<---snip------8<---snip------8<---snip---
> das Thema verbessern könnten. Dazu sehe ich die NG als das Mittel der Wahl.
Da kann ich jetzt nicht mitreden was den Druckerthread betrifft. Doch
eins würde ich noch gerne loswerden.
Ich denke mal es kommt ja nicht nur darauf an wie Frank den
"Fortschritt" beurteilt sondern alle Beteiligten, allen voran der
Eröffner des threads. Ich betrachte es ehrlich gesagt als egoistisch
wenn gar nicht klar ist ob Christian nunmehr sein Problem gelöst hat und
dennoch sein thread (war ja seine Frage bzw sein Problem) durch einen
anderen einfach für beendet erlärt wird.
>
> Grüße
> Paule
Gruß,
Peter
ich habe mir auch das Projekt heruntergeladen, kompiliert und (nur)
den Server gestartet. Das Projekt war die Version .NET 3.5 vom
06.08.2008. Frank bietet ja das Projekt für mehrere .NET Versionen an.
Bei mir wird das Serverfenster geöffnet, ich kann kurz lesen: ""Der
Server ist gestartet auf Port : ..... " etc. Dann wird der Inhalt des
Fensters weiss und das GUI reagiert nicht mehr.
Klar wenn ich dann (irgendwann später) den Client starte, verhält sich
das Programm wie gewünscht.
Zeile 45 im Server.cs muss blockieren. Dass steht auch in der MSDN
unter: http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.aspx
Zitat:
The TcpListener class provides simple methods that listen for and
accept incoming connection requests in BLOCKING SYNCHRONOUS MODE. You
can use either a TcpClient or a Socket to connect with a TcpListener.
Create a TcpListener using an IPEndPoint, a Local IP address and port
number, or just a port number. Specify Any for the local IP address
and 0 for the local port number if you want the underlying service
provider to assign those values for you. If you choose to do this, you
can use the LocalEndpoint property to identify the assigned
information, after the socket has connected.
Use the Start method to begin listening for incoming connection
requests. Start will queue incoming connections until you either call
the Stop method or it has queued MaxConnections. Use either
AcceptSocket or AcceptTcpClient to pull a connection from the incoming
connection request queue.THESE TWO METHODS WILL BLOCK. If you want to
avoid blocking, you can use the Pending method first to determine if
connection requests are available in the queue.
Ich sehe da keinen Interpretationsspielraum.
Gruss
Thomas
> Zeile 45 im Server.cs muss blockieren.
Das stellt keine von uns hier in Frage.
Lade den ganz rechten Download herunter:
[Download .NET 2.0 Server nicht UI-blockierend.]
http://dzaebel.net/Downloads/TcpClientServer4.zip
Synchrone Sockets brauchen nicht die UI
blockieren, das ist das grundlegende Missverständnis
von Peter. Peter denkt, synchrone Sockets lassen
die "UI einfrieren". Das ist falsch. Das eine hat mit
dem anderen aber nichts zu tun. Das eine ist
"Threading", das andere sind "Sockets/TcpClient".
Teste es mal :-)
habe das Beispiel "downgeloaded". Da ich nur ein VSTS 2008 besitze
musste ich es zuerst noch konvertieren ;-)
Also ich habe den Server (und nur den Server!) gestartet. Dann kommt
dein Hauptfenster und oben rechts ein Button "Beispiel". Wenn ich auf
den Clicken will passiert zunächst gar nix, dann erscheint die Sanduhr
und schliesslich wird der Titel des Fensters auf ''Server(Not
Responding)'' geändert.
Ich nehme an, dass das nicht das erwartete Verhalten ist? (Es sollte
eine MessageBox erscheinen mit dem Text "Obwohl der Server sich
momentan in einem blockierenden Receive befindet, ist das User
Interface responsefähig. :-)" ???)
Gruss
Thomas
ich habe mal dein Server.cs etwas abgeändert (war so frech)
....
/// <summary> S E R V E R </summary>
private void Form1_Load(object sender, EventArgs e)
{
IPAddress ipAdresse=null;
formInstance = this;
try
{
this.Show(); Application.DoEvents();
GetIpAdresse(ref ipAdresse, Dns.GetHostName());
tcpListener = new TcpListener(ipAdresse, Props.Port);
tcpListener.Start();
}
catch (Exception exp)
{
Melde("Beim Versuch der Auflösung der Addresse: " +
ipAdresse.ToString() + " enstand folgender Fehler:\r\n" +
exp.Message);
return;
}
try
{
new Thread(new ThreadStart(Execute)).Start();
}
catch (Exception exp)
{
Melde(exp.Message);
return;
}
}
private void Execute()
{
Melde("Der Server ist gestartet auf Port : " + Props.Port);
Melde("Der lokale Endpunkt ist :" + tcpListener.LocalEndpoint);
Melde("Warte auf Verbindung eines Clients ...");
while (!this.threadStopEvent.WaitOne(0, true))
{
if (tcpListener.Pending())
{
socket = tcpListener.AcceptSocket();
Melde("Client-Verbindung akzeptiert von: " +
socket.RemoteEndPoint);
new Thread(new ThreadStart(ReceiveHandler)).Start();
}
}
}
....
Wie du siehst habe ich das "warten auf eine Verbindung" in einen
eigenen Thread gepackt. Jetzt kann ich auf den Beispiel - Button
drücken woviel ich will und jedesmal popt eine MessageBox hoch.
Gruss
Thomas
> ich habe mal dein Server.cs etwas abgeändert (war so frech)
kein Problem, vollkommen richtig. Danke für Deinen Einsatz.
Wollte ich auch gerade machen und werde das auch
noch ins Netz stellen. Es wurde ja nicht der
erste Teil der Verbindung in einem Thread
abgehandelt. Das war ja aber sicher für die meisten
leicht ersichtlich.
Das Beispiel zeigt nur, dass:
"synchrone Sockets nicht die UI blockieren müssen."
Das ist das grundlegende Missverständnis von Peter hier.
Das sind zwei Paar Schuhe. Das eine ist "Threading", das
andere sind "Sockets / TcpClient".
> [Download .NET 2.0 Server nicht UI-blockierend.]
> http://dzaebel.net/Downloads/TcpClientServer4.zip
Weiter:
der ReceiveHandler() mit UTF-8 Encoding ist potentiell fehlerhaft,
falls bei Receive() eine Fragmentierung _zwischen_ Mehrbyte-Codes
auftritt...
(in der Praxis [lokal/intranet] mit kurzen Meldungen meist kaum
reproduzierbar)
Würde ich im Src mind. als Kommentar anmerken.
> ... bei Receive() eine Fragmentierung ...
Fragmentierung ist ganz normal zwischen TCP-Endpunkten,
wird aber schon innerhalb der Netzwerkschicht (s. ->ISO Modell)
"sauber" re-assembled (wieder zusammengefügt).
Hier ein detaillierter Artikel dazu und auch Implementationen
mit dem UTF8Encoding:
[Covert Channel Analysis and Data Hiding in TCP/IP]
http://napier.inchcolm.org/Portals/5/David%20Llamas%20Honours%20Project%202004.pdf
Hier auch ein "paar" Beispiele von Microsoft:
http://www.google.de/search?hl=de&q=site%3Amsdn.microsoft.com+TcpClient+UTF8
Ok. Tausend Dank für Deinen Test und Deine Bemühungen.
> Bei mir wird das Serverfenster geöffnet, ich kann kurz lesen: ""Der
> Server ist gestartet auf Port : ..... " etc. Dann wird der Inhalt des
> Fensters weiss und das GUI reagiert nicht mehr.
Ja, weil das die letzte Ausgabe mit der Methode Melde() ist, bevor
Accept() aufgerufen wird.
> Klar wenn ich dann (irgendwann später) den Client starte, verhält sich
> das Programm wie gewünscht.
Klar. Das ist ja der Grund warum Accept() blockieren MUSS, nämlich so
lange ein Client eben NICHT connected. Und wann ein Client sich
verbindet, weiß ein Server im allgemeinen nicht. Wenn sich ein Client
verbunden hat dann liefert Accept() den neuen Socket für diesen Client
zurück. Deswegen kann Accept() nicht zurückkehren und MUSS blockieren so
lange sich kein Client verbunden hat. Hatte ich aber alles schon
beschrieben übrigens.
> Zeile 45 im Server.cs muss blockieren.
Richtig. Hatte ich auch genau so beschrieben und erklärt doch Frank
antwortete dann recht sauer mit Zitat vom 1.8.2008 13:56:
>>nein, schau Dir einfach mein Beispiel an, dann siehst
>>Du, dass die da nichts blockiert Peter. Man, ist aber
>>auch schwer mit Dir.
Zu der GUI, die zwangsweise einfrieren MUSS wenn innerhalb LoadForm eine
blockierende Funktion aufgerufen wird meinte Frank, Zitat:
>>Quark, die friert nicht ein.
Dann kam übrigens auch schon das EOT von Frank.
Es ist eigentlich vollkommen egal welche blockierende Funktion man in
LoadForm aufruft, man hält dadurch das Laden der Form auf was zu diesen
Resultaten führen muss. Ich habe mir noch den Spaß gemacht und ein Menü
in die Form eingebaut, das ließ sich nicht bedienen, mit der Sanduhr an
der Maus erst recht nicht.
> Dass steht auch in der MSDN
> unter: http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.aspx
>
> Zitat:
>
> The TcpListener class provides simple methods that listen for and
> accept incoming connection requests in BLOCKING SYNCHRONOUS MODE. You
> can use either a TcpClient or a Socket to connect with a TcpListener.
> Create a TcpListener using an IPEndPoint, a Local IP address and port
> number, or just a port number. Specify Any for the local IP address
> and 0 for the local port number if you want the underlying service
> provider to assign those values for you. If you choose to do this, you
> can use the LocalEndpoint property to identify the assigned
> information, after the socket has connected.
>
> Use the Start method to begin listening for incoming connection
> requests. Start will queue incoming connections until you either call
> the Stop method or it has queued MaxConnections. Use either
> AcceptSocket or AcceptTcpClient to pull a connection from the incoming
> connection request queue.THESE TWO METHODS WILL BLOCK. If you want to
> avoid blocking, you can use the Pending method first to determine if
> connection requests are available in the queue.
>
> Ich sehe da keinen Interpretationsspielraum.
Ich habe es halt mit meinen Worten und auf deutsch beschrieben. Und auch
wenn es vielleicht nicht so elegant geklungen hat, so stimmt es dennoch.
Natürlich kann man jetzt sagen "...um blockieren zu verhindern müsste
man..." oder "...in echt müsste das natürlich als service ..." etc. Doch
ich habe halt vom IST Programm gesprochen und nicht von etwas dass es
nicht gibt, hatte stets hingewiesen welche Sample-App. ich meinte.
> Gruss
>
> Thomas
Vielen Dank für Deine Mühe Thomas und Deine Resultate bei Deinen Tests.
Gruß,
Peter
Thomas Hasler hat es doch verifiziert.
Er sagt "er klickt jetzt auf den Button
und alles klappt".
"Synchrone Sockets müssen nicht die UI
einfrieren" !
Das machst Du mit Threading.
Das sind zwei paar Schuhe. Das eine
sind die "Sockets / TcpClient", das andere
die Threads.
Sieh das doch endlich mal ein.
Das ist ja wirklich langsam lächerlich.
Zumal Dir Thomas das jetzt auch schon gesagt hat.
Oooops Thomas, das darfst Du aber nicht tun. Bei Frank funktioniert das
nur synchron. Immer wenn ein Server gestartet wird taucht aus dem Nichts
ein Client auf der sich sofort verbindet. ;-)
> Dann kommt
> dein Hauptfenster und oben rechts ein Button "Beispiel". Wenn ich auf
> den Clicken will passiert zunächst gar nix, dann erscheint die Sanduhr
> und schliesslich wird der Titel des Fensters auf ''Server(Not
> Responding)'' geändert.
Danke Thomas für Deine Beobachtung. Und jetzt bitte ich mal alle user
den thread nochmals zurückzuverfolgen. Genau daselbe hatte ich auch
gesagt. Dass eine Sanduhr kommt und dass ein "..not responding.." in der
Titlebar angezeigt wurde. Dann wurde der Fehler an MS gepostet.
> Ich nehme an, dass das nicht das erwartete Verhalten ist? (Es sollte
> eine MessageBox erscheinen mit dem Text "Obwohl der Server sich
> momentan in einem blockierenden Receive befindet, ist das User
> Interface responsefähig. :-)" ???)
Also diese Variante des Beispiels habe ich noch nicht getestet Thomas,
doch ich glaube Dir Deine Beobachtungen. Ich denke mal dass es seltsam
ist dass es offensichtlich bei Frank funktioniert. Bei Frank
funktionieren offenbar Programme die LoadForm() blockieren!? :(
> Gruss
>
> Thomas
Tausend Dank für deine Tests und Deinen Aufwand, Thomas.
Grüße,
Peter
P.S. Ich frage jetzt mal alle user hier warum eine blockierende Funktion
wohl so heißt und warum sie überhaupt blockiert. Mal so als Freitag
Nachmittag Techno Quiz Frage...
Deine Postings sind jetzt tiefstes Niveau.
Ich hatte das von Anfang an richtig eingeschätzt.
Beachte, Newsgroups sind kein rechtsfreier
Raum.
Thomas Hasler hat selber schon gemerkt,
das er nur den Anfang des Server-Codes
in einen Thread stecken muss.
Dann funktioniert mein Code!
Er sagt:
"Jetzt kann ich auf den Beispiel -
Button drücken woviel ich will und
jedesmal popt eine MessageBox hoch."
Die Anwendung ist also responsefähig.
Obwohl synchrone Sockets benutzt werden.
Das Beispiel zeigt, dass:
"synchrone Sockets nicht die UI blockieren müssen."
Das ist Dein grundlegendes Missverständnis Peter.
Das sind zwei Paar Schuhe. Das eine ist "Threading", das
andere sind "Sockets / TcpClient".
Gut gemacht Thomas. Doch in diesem Falle ist sogar das Pending()
überflüssig, würde ich mal behaupten. Der Accept() könnte auch direkt
aufgerufen werden da ja die Thread-Funktion "Execute()" eben von einem
separaten thread bedient wird den du mit new Thread() innerhalb
LoadForm() eingerichtet hast. Dadurch kann sich LoadForm() normal
beenden und blockiert eben nicht. Allenfalls müsste man bei Melde() noch
einen Invoke() berücksichtigen da ein anderer thread auf GUI-controls
zugreift!?
Wenn man nochmals den Diskussionsthread zurückverfolgt kann man lesen
dass ich geschrieben hatte, dass ich in meiner App die asynchronen
Socket Funktionen benutze und warum. Die machen nämlich das was Du
Thomas jetzt "von Hand" gemacht hast. Frank meinte hierzu das wäre das
Gleiche, ist es aber nicht.
Danke für Deine Bemühungen Thomas,
Gruß
Peter
Deine Postings sind jetzt tiefstes Niveau.
Ich hatte das von Anfang an richtig eingeschätzt.
Beachte, Newsgroups sind kein rechtsfreier
Raum.
Thomas Hasler hat selber schon gemerkt,
das er nur den Anfang des Server-Codes
in einen Thread stecken muss.
Dann funktioniert mein Code!
Er sagt:
"Jetzt kann ich auf den Beispiel -
Button drücken woviel ich will und
jedesmal popt eine MessageBox hoch."
Die Anwendung ist also responsefähig.
Obwohl synchrone Sockets benutzt werden.
Das Beispiel zeigt, dass:
"synchrone Sockets nicht die UI blockieren müssen."
Das ist Dein grundlegende Missverständnis Peter.
Das sind zwei Paar Schuhe. Das eine ist "Threading", das
andere sind "Sockets / TcpClient".
Hast Du es jetzt endlich begriffen Peter?
"synchrone Sockets müssen nicht die UI blockieren!!"
Das ist Dein grundlegendes Missverständnis hier Peter.
Das sind zwei Paar Schuhe. Das eine ist "Threading", das
andere sind "Sockets / TcpClient".
BTW: Das Du hier andere Leute falsch zitierst,
ist unterstes Niveau. Aber ich bleibe lieber beim technischen.
Das ist aber keine neue Erkenntnis Frank und das hatte ich auch nie
behauptet. Einfach nochmals meinen Beitrag vom 2.8.2008 0:17 Uhr lesen,
schon da hatte ich den Grund des blockierens der GUI beschrieben.
Ich hatte von dem Beispiel gesprochen und Thomas hat ja auch
festgestellt dass die GUI einfror. Das liegt natürlich überhaupt nicht
an der Socket-Funktionalität. Jede andere blockierende Funktion,
aufgerufen innerhalb LoadForm() verhindert dass das Laden einer Form zu
Ende geführt wird und dewegen MUSS die GUI dann einfrieren. Mit anderen
Worten: LoadForm() darf man nicht aufhalten.
> Das ist das grundlegende Missverständnis von Peter hier.
s. o.
Gruß,
Peter
danke für die Blumen. Wir verstehen uns ;-)
Ich möchte gerne beim "Freitag Nachmittag Techno Quiz" mitmachen.
Also "Warum blockiert TcpListener.AcceptSocket() überhaupt?"
Mein Vorschlag:
1. Die Methode TcpListener.AcceptSocket( ) hat als Rückgabewert einen
Socket
2. Um diesen Socket zurückzugeben muss sie ihn erzeugen, sprich den
Constructor callen
3. Es gibt 2 Konstruktoren, diese verlangen jedoch Informationen wie
IP-Adresse des Senders, Protocolversion etc. (Sind ja BerkleySockets)
4. Um diese Informationen zu bestimmen braucht es einen (TCP) -
Request in der (Network-)Messagequeue des OS .
Also muss ich warten bis dieser Request in der Queue ist, ihn
auslesen, auswerten etc. dann kann ich den Socket erzeugen und
zurückgeben.
Was meint ihr dazu?
Viel Spass beim Quizzen
nur die 'Reihenfolge' des _Bytestreams_ ist so gewährleistet,
aber nicht die Fragmentierung an und für sich 'behoben'!
Und spätestens falls die Textmeldungen viele KB lang werden
ergibt sich eh eine Fragmentierung
(mind. Intranet/Internet markant, typ. beginnend bei ca. 1.5KB).
Und diese Fragmentierung ist immer 'zufällig',
kann also ggf mitten zwischen UTF8 multibyte-codes zu liegen kommen.
Dies ist auch _absolute_ Grundlage von Streams generell.
Lies entsprechend auch MSDN zB bei Dateien:
FileStream.Read
"An implementation is free to return fewer bytes than requested..."
Falsche UTF8-Codes können übrigens schon
100% immer reproduzierbar in deinem Server Src auftreten,
falls ein Multibyte-Code genau an deiner 100-Byte Buffergrenze ('maxBuffer')
beginnt.
Ein grösserer Buffer löst den Fall aber nicht,
spätestens ab etlichen KBs gibts das Problem so oder so (bzw umso mehr).
Einzige Lösung: Längenpräfixe(Header) oder Delimiter o.ä. + Logik,
ala BinaryReader.ReadString, StreamReader.ReadLine.
Oder hier ggf. eigene UTF-8 Sequenz-Erkennung/Überlappung.
>> "synchrone Sockets nicht die UI blockieren müssen."
>
> Das ist aber keine neue Erkenntnis Frank
Peter, wenn Du das jetzt einsiehst, ist es wirklich eine
Erlösung für alle hier - vielen Dank :-)
Vom ersten Posting an habe ich versucht Dir das
zu erklären. An der Stelle können wir gerne beenden.
> Ich hatte von dem Beispiel gesprochen und Thomas
> hat ja auch festgestellt dass die GUI einfror.
Thomas Hasler hat erkannt, dass die GUI *nicht* einfrieren
muss (in seinem Nachtrag). Er sagt:
"Jetzt kann ich auf den Beispiel-Button drücken woviel
ich will und jedesmal popt eine MessageBox hoch."
Die GUI friert also nicht ein. Ausserdem hatte ich bereits
gesagt gehabt, das Beispiel **eins** einfriert.
Das stand gar nicht zur Diskussion:
http://groups.google.com/group/microsoft.public.de.german.entwickler.dotnet.csharp/msg/32313c20ded070b5
Deswegen wurde ja noch ein anderes gemacht, um zu
zeigen, dass synchrone Sockets nicht die UI einfrieren müssen.
> Das liegt natürlich überhaupt nicht an der Socket-Funktionalität.
eben, "Sockets" und "Threading" sind verschiedene Paar
Schuhe. Synchrone Sockets müssen die UI nicht einfrieren.
Halten wir also für Nachwelt fest:
"Synchrone Sockets müssen nicht die UI einfrieren!!!".
> Ein grösserer Buffer löst den Fall aber nicht,
> spätestens ab etlichen KBs gibts das Problem so oder so (bzw umso mehr).
>
> Einzige Lösung: Längenpräfixe(Header) oder Delimiter o.ä. + Logik,
> ala BinaryReader.ReadString, StreamReader.ReadLine.
> Oder hier ggf. eigene UTF-8 Sequenz-Erkennung/Überlappung.
In den Beispielen, die ich verlinkt habe, werden Decoder beim
UTF8Encoding benutzt. Die habe ich bei mir noch nicht eingebaut.
Ich kann gerne mal nachschauen, was hier "best practice" ist.
Solange ich noch nichts nähreres zur besten Lösung weiss,
werde ich mal einen Hinweis zum UTF8Encoding im downloadbaren
Code machen. Wenn ich nähere Informationen habe poste ich wieder.
Der Bsp-Source auf
TcpClient.GetStream-Methode
<URL:http://msdn.microsoft.com/de-de/library/system.net.sockets.tcpclient.getstream.aspx>
hat übrigens potentiell dasselbe Problem!
Die VB-Variante übrigens sendet UTF8, empfängt aber ASCII,
was die Qualität dieser MSDN-Bsp schon in Frage stellt.
Andererseits ist dort der Source so derart simpel/unvollständig,
dass man ihn wohl nicht zu ernst nehmen darf,
höchstens als grobe Text-Vorlage für Copy&Paste.
> Qualität dieser MSDN-Bsp
Also es ist klar, dass nicht alle MSDN-Beispiele das
gelbe vom Ei sind. Das kennen wir aus den Jahren bereits ...
Aber der Umkehrschluss wäre auch nicht richtig
und Deine These ist (für mich) nicht ausreichend geklärt/geprüft/
belegt.
Die "best practice" versuche ich noch in Erfahrung zu bringen
und werde sie hier posten, aber solange kann ich dazu nicht
viel mehr sagen, bzw. muss mich da enthalten.
Aus Erfahrung weiss ich zumindest, dass Du in diesem
Gebiet immer fundierte Aussagen postest.
Dieser Satz wurde jetzt (in einem anderen Posting)
von Peter akzeptiert mit der Antwort:
"Das ist aber keine neue Erkenntnis [...]".
Damit besteht für mich kein Grund mehr zu intervenieren.
War wohl dann insgesamt ein Missverständnis.
"Frank Dzaebel" <po...@franksseite.de> schrieb:
>> Ein grösserer Buffer löst den Fall aber nicht,
>> spätestens ab etlichen KBs gibts das Problem so oder so (bzw umso mehr).
>>
>> Einzige Lösung: Längenpräfixe(Header) oder Delimiter o.ä. + Logik,
>> ala BinaryReader.ReadString, StreamReader.ReadLine.
>> Oder hier ggf. eigene UTF-8 Sequenz-Erkennung/Überlappung.
>
>In den Beispielen, die ich verlinkt habe, werden Decoder beim
>UTF8Encoding benutzt. Die habe ich bei mir noch nicht eingebaut.
Mit dem 'Decoder'-Objekt könnte man "zerschnittene" UTF-8-codierte Zeichen
erkennen und nicht decodieren lassen. Beispiel:
\\\
const string text = "mÄr";
byte[] bytes = Encoding.UTF8.GetBytes(text);
MessageBox.Show(bytes.Length.ToString());
byte[] part1 = new byte[2];
Buffer.BlockCopy(bytes, 0, part1, 0, part1.Length);
Decoder decoder = Encoding.UTF8.GetDecoder();
int count1 = decoder.GetCharCount(part1, 0, part1.Length);
MessageBox.Show(count1.ToString());
char[] chars1 = new char[count1];
decoder.GetChars(part1, 0, part1.Length, chars1, 0);
MessageBox.Show(new string(chars1));
///
Außerdem können die nicht decodierbaren Daten bei Vorliegen weiterer Daten
decodiert werden (siehe Parameter 'flush' von 'GetCharCount').
Aus "Decoder.GetCharCount-Methode ( Byte *, Int32, Boolean) (System.Text)",
<URL:http://msdn.microsoft.com/de-de/library/57yed56t.aspx>:
| Wenn 'GetChars' aufgerufen wird und dabei 'flush' auf 'false' festgelegt
| ist, speichert der Decoder die nachfolgenden Bytes am Ende des
| Datenblocks in einem internen Puffer und verwendet diese im nächsten
| Decodierungsvorgang. Die Anwendung muss 'GetCharCount' für einen
| Datenblock unmittelbar vor dem Aufruf von 'GetChars' für denselben Block
| aufrufen, sodass nachfolgende Bytes aus dem vorherigen Block in die
| Berechnung einbezogen werden.
[In der ersten Zeile sollte es wohl "Wenn 'GetCharCount' aufgerufen wird
[...]" heißen.]
--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://dotnet.mvps.org/dotnet/faqs/>
> > In den Beispielen, die ich verlinkt habe, werden Decoder beim
> > UTF8Encoding benutzt. Die habe ich bei mir noch nicht eingebaut.
>
> Mit dem 'Decoder'-Objekt könnte man "zerschnittene" UTF-8-codierte Zeichen
> erkennen und nicht decodieren lassen. Beispiel:
ja, ich habe Thomas in meinem ersten Link auch schon
so ein Beispiel verlinkt:
http://napier.inchcolm.org/Portals/5/David%20Llamas%20Honours%20Project%202004.pdf
So jetzt gehts zum Badminton ...
Ja Frank das stimmt schon, blockierende Socket-Funktionen müssen nicht
das GUI einfrieren, aber sie KÖNNEN es, und das war in Deinem Beispiel
mit der Version zu dem Datum als ich es testete so. Thomas hatte - nach
meiner Aufforderung dass andere user das doch bitte auch mal testen
sollen - genau das gleiche Ergebnis wie ich, und jetzt reden wir
mittlerweile über eine vollkommen andere Version, welche Thomas derart
abänderte in dem er die blockierende Funktion in einen thread
auslagerte. Dadurch wird LoadForm nicht blockiert im Gegensatz zu der
Version ohne thread. Er hatte das gleiche Ergebnis wie ich, weiße GUI,
Sanduhr, application not responding... Warum wirfst Du mir dieses
Testergebnis eigentlich vor?
Das ist jetzt aber auch nicht gerade fair dass wir jetzt plötzlich von
einer ganz anderen, korrigierten Version reden. Jedenfalls befürworte
ich eher solch ein Beispiel wo nichts blockiert, hilfesuchenden usern
anzubieten. Noch besser aber eine Implementation mit den asynchronen
Socketfunktionen die das erzeugen eines threads ja bereits kapseln.
Gruß,
Peter
Ach, jetzt bin also ich für das Niveau verantwortlich. Welches "Recht"
habe ich denn verletzt Deiner Meinung nach?
> Thomas Hasler hat selber schon gemerkt,
> das er nur den Anfang des Server-Codes
> in einen Thread stecken muss.
> Dann funktioniert mein Code!
"Nur" ist gut. Es war aber nicht diese neuere Version die ich getestet
habe, das ist Dir schon klar, oder? Oder erwartest Du jetzt von mir dass
ich Programme teste die es erst in der Zukunft geben wird???
Dass Thomas aber bevor er die blockierende Funktion in einen thread
steckte, dieselben Ergebnisse hatte als ich, kehrst Du einfach unter den
Teppich.
> Er sagt:
>
> "Jetzt kann ich auf den Beispiel -
> Button drücken woviel ich will und
> jedesmal popt eine MessageBox hoch."
Klar, mit "Jetzt" meint er eine neuere, korrigierte Version.
Gruß,
Peter
> Hast Du es jetzt endlich begriffen Peter?
Und auf welchem Niveau bist Du eigentlich.
Ja, und das freut mich. ;-)
> Ich möchte gerne beim "Freitag Nachmittag Techno Quiz" mitmachen.
Na klar, sollst Du auch. Je mehr desto besser.
> Also "Warum blockiert TcpListener.AcceptSocket() überhaupt?"
>
> Mein Vorschlag:
>
> 1. Die Methode TcpListener.AcceptSocket( ) hat als Rückgabewert einen
> Socket
Richtig.
> 2. Um diesen Socket zurückzugeben muss sie ihn erzeugen, sprich den
> Constructor callen
Ok, ist aber erst mal nicht so wichtig WIE das gemacht wird, eher WANN. ;-)
> 3. Es gibt 2 Konstruktoren, diese verlangen jedoch Informationen wie
> IP-Adresse des Senders, Protocolversion etc. (Sind ja BerkleySockets)
Sind BerkleySockets, richtig. Auch wenn MS noch so viele wrapper
drumherum baut. Wieso 2 Konstruktoren?
> 4. Um diese Informationen zu bestimmen braucht es einen (TCP) -
> Request in der (Network-)Messagequeue des OS .
Richtig. Weiß der Server wann dieser auftaucht?
> Also muss ich warten bis dieser Request in der Queue ist, ihn
> auslesen, auswerten etc. dann kann ich den Socket erzeugen und
> zurückgeben.
Du sagst "also muss ICH warten", also bist jetzt gerade DU mal der
Socket, okay, wieso nicht.
> Was meint ihr dazu?
>
> Viel Spass beim Quizzen
Ja, nicht schlecht und vor allem nicht falsch. Doch Du hast eher
beschrieben WAS abläuft, aber der Grund für das Blockieren kam mir dabei
jetzt etwas zu kurz.
Ich versuch jetzt mal meine Version, okay:
1.) Also du rufst wie auch immer Accept() auf. Wichtig dabei ist das was
Du gesagt hast, der Rückgabewert von Accept(). Hier mal Pseudo-Code:
Socket cs = ls.Accept(); // Accept(), unsere blockierende Funktion
Warum blockiert Accept() und was ist "ls" und was ist "cs"? Nun, "ls"
ist der bereits an den lokalen Endpunkt gebundene "Listening Socket".
Über diesen werden NIE die Nutzdaten gesendet, er dient NUR zur
Kontaktaufnahme für einen remote Client. Verbindet sich ein Client wird
ein NEUER socket "cs" (client socket) zurückgeliefert. Dies ist dann der
socket mit dem der Server mit diesem Client kommuniziert. Ein Server,
welcher x-beliebig viele Client-Connections erlaubt, übergibt diesen
socket "cs" z. B. einer list oder einem hash. Diesem socket kann man die
IP und port-nummer des Clients entlocken wie Du richtig unter Deinem
Punkt 3.) sagtest. Deswegen läuft üblicherweise das Accept() in einer
Schleife bzw. es wird also immer wieder erneut aufgerufen damit sich
weitere Clients zum Server verbinden können. Die zurückgelieferten
sockets dürfen natürlich nicht nur in eine collection gesteckt werden,
sondern es muss für jeden socket ein entsprechendes, am Besten
asynchrones handling bereitgestellt werden (rcv, close). Das Send() zum
Client erfolgt oftmals als response auf einen rcv vom Client und wird
somit synchron, vom Server aus gesehen, benutzt.
Aber jetzt zum Punkt 4.) von Dir. Das ist der Knackpunkt, der Grund für
das blockieren überhaupt. Nach dem Motto "..ach wüsste eine Bank doch
wann die Bankräuber kommen...". Ja klar, es braucht einen TCP-request
zum "wartenden" und "blockierenden" Accept(), denn wie sollte Accept()
zurückkehren und sich beenden um dann vor allem die AUFRUFENDE FUNKTION
NICHT MEHR ZU BLOCKIEREN (ja, es ist eine gute Idee sie in einem thread
aufzurufen aber auch in diesem thread blockiert sie, nur der thread
blockiert nicht den Rest der GUI/App) und letztendlich den neuen socket
zum kommunizieren mit dem Client zurückzuliefern.
Wichtig ist mir bei einer blockierenden Funktion auch der Sinn einer
solchen. Natürlich ist eine blockierende Funktion nicht nutzlos, gemein
oder bösartig. Dann das blockieren hat seinen NATÜRLICHEN GRUND und die
blockierende Funktion ist ja nicht untätig, sie macht ja was und wenn es
eben nur ein Warten auf einen Client ist. Doch die AUFRUFENDE FUNKTION
MUSS DANN EBEN LEIDER AUCH WARTEN und das hat doch eine so schöne Form
gar nicht verdient, soll doch Accept() warten aber ICH SCHÖNE GUI, will
bestaunt werden. Also bitte nicht meine Initialisierungsroutine
blockieren, sonst werde ich eiskalt und friere ein (sagte die GUI)! ;-)
Nehmen wir doch mal eine Wait() Funktion. Zum Beispiel Wait(60000); Was
passiert dann? Wäre jetzt ein neues Freitag Abend Techno Quiz. Aber ich
sage mal, die Funktion ist auch nicht nutzlos oder böse, sie wartet
einfach 60 Sekunden. Sie tut selber natürlich was, nämlich bis 60
zählen. Doch die AUFRUFENDE Funktion wird halt genötigt, 60 Sekunden zu
warten. Aber wenn das gewollt ist dann passt es auch. Würden wir diese
Wait(60000) Funktion innerhalb LoadForm() aufrufen, dann wäre die GUI ja
"bloss" für 60 Sekunden eingefroren. Doch da die Zeit die Eigenschaft
hat zu vergehen, gehen die 60 Sekunden relativ schnell vorbei und dann
darf die GUI wieder auftauen. Doch was wenn bei unserem Server mit dem
Accept() kein Mensch im Universum die IP oder den Port des listening
sockets kennt und es keine Client-Connection gibt? Arme GUI, Du wirst
Eiszapfen kriegen. :(
War das jetzt gemein von mir in dem Beispiel-Projekt den Start des
Clients einfach mal wegzulassen und nur den Server zu starten? Wie
gefällt euch meine Erklärung einer blockierenden Funktion? Danke.
Gruß,
Peter
Zu Befehl Herr Forumsoberaufseher!
> "synchrone Sockets müssen nicht die UI blockieren!!"
>
> Das ist Dein grundlegendes Missverständnis hier Peter.
> Das sind zwei Paar Schuhe. Das eine ist "Threading", das
> andere sind "Sockets / TcpClient".
Frank, eine "blockierende Funktion" wie etwa Accept() kehrt auch,
aufgerufen innerhalb eines threads, erst dann zurück, wenn sich ein
Client verbunden hat. Können wir uns darauf einigen? Du hattest
geschrieben dass eine blockierende Funktion nicht mehr blockiert, wenn
sie etwa in einer Schleife aufgerufen wird. Sie würde also, in einer
Schleife aufgerufen, nicht mehr blockieren und sofort zurückkehren?
Sorry, aber das stimmt einfach nicht. Das blockieren bzw. synchrone
Verhalten liegt in der Natur der Tatsache, dass NICHT VORAUSGESEHEN
WERDEN KANN, wann sich ein client verbindet. Das und nichts anderes ist
der Grund des blockierens von Accept().
> BTW: Das Du hier andere Leute falsch zitierst,
> ist unterstes Niveau. Aber ich bleibe lieber beim technischen.
Was habe ich denn wo falsch zitiert?
Gruß,
Peter
> blockierende Socket-Funktionen müssen nicht
> das GUI einfrieren, aber sie KÖNNEN es
genau, so darf man es auch ausdrücken.
Auch asynchronen Sockets *können*
blockieren. IMHO ists jetzt aber auch ok, jetzt
fangen wir lieber nicht von vorne an. Irgendwas
ist schief gelaufen. Was solls. Jetzt haben
wir doch gerade einen guten Abschluss gefunden.
> ... anderen, korrigierten Version reden.
ich möchte nicht wieder damit anfangen Peter.
Du hast Dir irgendwann mal die erste Version
genommen und hast davon abgeleitet,
das synchrone Sockets die UI blockieren,
(mein Verständnis da, hast Du sicher anders gemeint)
was sie ja nicht tuen, denn das hängt ja
von der Thread-Codierung ab.
Danach hast Du IMHO immer nur noch dieses
Beispiel im Auge gehabt. Ich aber schon recht
früh von der allgemeinen Unabhängigkeit des
UI-Interfaces und Sockets gesprochen (und gedacht).
Sicher habe ich Dir das schlecht rüber gebracht,
da Du es ja offensichtlich so nicht verstanden hast.
> Jedenfalls befürworte ich eher solch ein Beispiel
> wo nichts blockiert,
Natürlich, das tun wir doch alle, deswegen habe ich
dann ja auch ein nicht blockierendes mit synchronen
Sockets gemacht, damit mans sieht.
Ich habe auch extra in meiner Webseite stehen,
dass dies ein sehr einfaches Beispiel ist!!
100% optimale Code zu schreiben ist enorm
aufwändig. Gerade die letzten 10% dauern oft so
lange wie die ersten 90. Wenn gute Hinweise
kommen, baue ich die immer gerne ein.
> Noch besser aber eine Implementation mit den asynchronen
> Socketfunktionen die das erzeugen eines threads ja bereits kapseln.
Auch das Thema der asynchronen Sockets kann man
eimal in eine Webseite beschreiben (ist natürlich von
anderen auch schon gemacht). Ich finde die vom
Ansatz her etwas komplizierter für Anfänger (ich selber mache
es durchaus öfter), aber Du ja nicht - was solls - dann haben
wir verschiedene Meinungen.
Nur in meiner Webseite sind halt die synchronen thematisiert.
Ich bin jetzt ein wenig müde über dieses Thema ... ;-)
wir sind uns einig:
"synchrone Sockets müssen nicht die UI blockieren".
Ich habe keine Einwände mehr.
ich wäre dafür das Ganze hier so stehen zu lassen. Aus meiner Sicht
hatte jeder von euch zweien mit seinem Standpunkt "recht". Das ist
doch das Schöne an unserem Beruf, es gibt eigendlich keine absolute
"Wahrheit". Man kann ein Problem immer mit diversen Methoden,
Patterns, Programmiersprachen etc. lösen. Hat es schon jemals einen
Kunden interessiert wie wir das gemacht haben, wenn die Lösung ihn
zufriedenstellt?
Genug philosophiert, ich mache jetzt Wochenende. Genehmige mir noch
ein Bier. Tut das auch.
Bis bald
Thomas
Doch es sind nicht die Sockets die synchron oder asynchron sind, sondern
die Socket-Funktionen.
> IMHO ists jetzt aber auch ok, jetzt
> fangen wir lieber nicht von vorne an. Irgendwas
> ist schief gelaufen. Was solls. Jetzt haben
> wir doch gerade einen guten Abschluss gefunden.
Ok, Frank, nichts für ungut. Liegt nun wirklich nicht in meiner Absicht
irgendwelche "wars" zu starten, das liegt mir fern.
>> ... anderen, korrigierten Version reden.
>
> ich möchte nicht wieder damit anfangen Peter.
> Du hast Dir irgendwann mal die erste Version
> genommen und hast davon abgeleitet,
> das synchrone Sockets die UI blockieren,
> (mein Verständnis da, hast Du sicher anders gemeint)
> was sie ja nicht tuen, denn das hängt ja
> von der Thread-Codierung ab.
Ok, auch wenn Du nichts mehr davon hören willst, ich will nun wirklich
auch nicht mehr "von vorne" anfangen, aber lass mich doch bitte sagen
dass die Version mit der ich testete eben keinen "thread" hatte. :(
> Danach hast Du IMHO immer nur noch dieses
> Beispiel im Auge gehabt. Ich aber schon recht
> früh von der allgemeinen Unabhängigkeit des
> UI-Interfaces und Sockets gesprochen (und gedacht).
Ja, gebe ich ja auch zu und hatte ich auch stets geschrieben, damit da
keine Missverständnisse auftreten. Ich habe sogar auf den link verwiesen
damit jedermann weiß welches Beispiel ich meine.
Deswegen ist es doch auch gut dieses Beispiel so stehen zu lassen damit
user auch sehen was passieren kann wenn man die socket-Funktionen so
aufruft. Ist eigentlich sogar ähnlich der O'Reilly head-first Methodik.
> Sicher habe ich Dir das schlecht rüber gebracht,
> da Du es ja offensichtlich so nicht verstanden hast.
Tut mir leid wenn ich jetzt letztens nur auf der eingefrorenen GUI
rumgeritten
bin, doch Thomas hatte ja das gleiche Ergebnis. Nicht falsch verstehen,
ich schätze es sehr wie Du den usern hilfst, welches Wissen Du hast und
dass Du auch so viele Beispiele frei zum download anbietest. Du schätzt
mich falsch ein wenn Du denkst ich würde das nicht honorieren. Geärgert
hat mich dann halt aber doch Dein "Quatsch, die friert nicht ein....".
>> Jedenfalls befürworte ich eher solch ein Beispiel
>> wo nichts blockiert,
>
> Natürlich, das tun wir doch alle, deswegen habe ich
> dann ja auch ein nicht blockierendes mit synchronen
> Sockets gemacht, damit mans sieht.
Ja super, habe ich noch nicht angeschaut. Auch das was Du mir nanntest,
viertes download oder so ähnlich, habe ich nicht gefunden. Das vierte
download auf Deiner website ist ein CD-drive öffnen sample. :(
> Ich habe auch extra in meiner Webseite stehen,
> dass dies ein sehr einfaches Beispiel ist!!
Ja okay, dann hast Du meine postings aber nur überflogen, denn ich sagte
nie dass es ist schlimm ist in diesem Minimal-Beispiel mit dem server
und client und der einfachen Textbox, dass es ein einfaches Beispiel
ist. Natürlich hast Du Recht dass newbies in Socket-Programmierung erst
mal einfache Beispiele brauchen. Doch man sollte vielleicht darauf
hinweisen dass das alles eher synchron abläuft weil der client gleich
mitgestartet wird.
> 100% optimale Code zu schreiben ist enorm
> aufwändig. Gerade die letzten 10% dauern oft so
> lange wie die ersten 90. Wenn gute Hinweise
> kommen, baue ich die immer gerne ein.
Ja, da gebe ich Dir Recht. Meine Socket-Server die in Taiwans
Filament-Industrie
laufen arbeiten alle mit blockierenden sockets. Juckt aber nicht weiter
weil es
jeweils eigene Prozesse sind die keinerlei GUI haben.
>> Noch besser aber eine Implementation mit den asynchronen
>> Socketfunktionen die das erzeugen eines threads ja bereits kapseln.
>
> Auch das Thema der asynchronen Sockets kann man
> eimal in eine Webseite beschreiben (ist natürlich von
> anderen auch schon gemacht). Ich finde die vom
> Ansatz her etwas komplizierter für Anfänger (ich selber mache
> es durchaus öfter), aber Du ja nicht - was solls - dann haben
> wir verschiedene Meinungen.
He he, Frank da muss ich widersprechen. Lies noch mal meine ersten
postings. Im Gegenteil hatte grade ich auf die asynchronen hingewiesen
und dass ich diese bevorzuge. Wieso behauptest Du jetzt das Gegenteil?
Ich hatte doch geschrieben dass die asynchronen Methoden das einrichten
eines Hintergundthreads welcher dann am socket pollt bereits beinhaltet.
Ja, die sind für Einsteiger wohl schwerer zu verstehen. Am Besten wäre
es wohl erst mal zu zeigen wie man es falsch macht, dann wie man es
richtig macht wie etwa das einrichten eines threads mit einem Poll()
welcher dann die events an callbacks verteilt, und dann schließlich
nochmal letzteres aber dann gekapselt von den asynchronen Funktionen.
Was hältst Du davon?
> Nur in meiner Webseite sind halt die synchronen thematisiert.
Ja, ist schon seltsam dass sich noch nicht mal der Thread-Eröffner
Christian für meinen code interessiert hat, obwohl er ja ursprünglich
das Problem hatte (oder immer noch hat). Aber vielleicht sind ihm ja die
asynchronen C# Socket-Funktionen wirklich zu kompliziert.
> Ich bin jetzt ein wenig müde über dieses Thema ... ;-)
> wir sind uns einig:
> "synchrone Sockets müssen nicht die UI blockieren".
> Ich habe keine Einwände mehr.
Habe auch keine Einwände mehr, nur 'ne klitzekleine Anmerkung wenn Du
gestattest. Warum bist Du nie auf das LoadForm() Thema eingegangen? Sag
mir doch ganz offen ob ich falsch liege oder richtig. Vergiss mal ganz
die Socket-Thematik. Ist es guter Stil innnerhalb dieses events
CPU-intensiven code (versprochen, ich fang jetzt nicht mehr wieder mit
dem Wörtchen blo..ren an) unterzubringen?
> ciao Frank
> --
> Dipl.Inf. Frank Dzaebel [MCP/MVP C#]
> http://Dzaebel.NET
Grüße und Danke für Deine Beteiligung auch nach EOT,
war das jetzt wirklich so unfruchtbar? Ich finde nicht.
Peter
> dass die Version mit der ich testete eben keinen "thread" hatte.
Das war das Verhängnis. Ich meinte/sprach nie irgendeine
spezielle Version an, sondern sprach über synchrone
Sockests und dass die nicht blockiren müssen, sprich
nicht die UI einfrieren müssen.
> Tut mir leid wenn ich jetzt letztens nur auf der eingefrorenen GUI
> rumgeritten bin, doch Thomas hatte ja das gleiche Ergebnis.
Nein, er hatte gemerkt, dass er jetzt seine Buttons
drücken kann und nichts mehr einfriert!
Du hast da das *erste* Posting von ihm herausgegriffen.
Im *zweiten* unmittelbar darauf revidiert hatte er es eingesehen.
Denn das eine ist Threading, das andere sind Sockets, eine
GUI muss ja bei synchronen Sockets nicht einfrieren.
> ich schätze es sehr wie Du den usern hilfst, welches Wissen Du hast und
> dass Du auch so viele Beispiele frei zum download anbietest. Du schätzt
> mich falsch ein wenn Du denkst ich würde das nicht honorieren. Geärgert
> hat mich dann halt aber doch Dein "Quatsch, die friert nicht ein....".
Das hatte ich auch im Posting danach sofort
revidiert und gesagt in meinem Server-Beispiel (dem ersten)
schon!
> > Natürlich, das tun wir doch alle, deswegen habe ich
> > dann ja auch ein nicht blockierendes mit synchronen
> > Sockets gemacht, damit mans sieht.
>
> Ja super, habe ich noch nicht angeschaut.
Thomas Hasler hat das schon getestet.
Es ist der ganz rechte Download in meiner Seite.
> Auch das was Du mir nanntest, viertes download
> oder so ähnlich, habe ich nicht gefunden. Das vierte
> download auf Deiner website ist ein CD-drive öffnen sample. :(
Hier ganz rechts (Thomas hatte den Download schon gefunden) :
Ggf. F5 für aktualisieren des IE Caches drücken:
[Client-Server Kommunikation mit dem TcpClient und TcpListener]
http://dzaebel.net/TcpClientServer.htm
> Natürlich hast Du Recht dass newbies in Socket-Programmierung erst
> mal einfache Beispiele brauchen. Doch man sollte vielleicht darauf
> hinweisen dass das alles eher synchron abläuft weil der client gleich
> mitgestartet wird.
Also Client und Server muss man in dem Szenario nicht
unbedingt synchron zu starten, es kann zuerst der
Server starten, dann der Client. Es ist nur sehr praktisch
für einen Anfänger, wenn er mal eben F5 drücken
kann und die beiden starten hoch (intern dann schon nacheinander).
> > Auch das Thema der asynchronen Sockets kann man
> > eimal in eine Webseite beschreiben (ist natürlich von
> > anderen auch schon gemacht). Ich finde die vom
> > Ansatz her etwas komplizierter für Anfänger (ich selber mache
> > es durchaus öfter), aber Du ja nicht - was solls - dann haben
> > wir verschiedene Meinungen.
>
> He he, Frank da muss ich widersprechen. Lies noch mal meine ersten
> postings. Im Gegenteil hatte grade ich auf die asynchronen hingewiesen
> und dass ich diese bevorzuge. Wieso behauptest Du jetzt das Gegenteil?
Lies noch mal das oben gequotete. "*Ich* finde die vom Ansatz her
komplizierter". *Du* nicht, Du bevorzugst sie ja.
> Ja, ist schon seltsam dass sich noch nicht mal der Thread-Eröffner
> Christian für meinen code interessiert hat,
Das muss nichts heissen. Asynchron gibt es in vielen Gebieten
im Framework und überall das gleiche: Die asynchronen Verfahren
werden eher selten benutzt. Irgendetwas gefällt den Leuten daran
nicht so. Schliesslich bewege ich mich hier in der NG schon
ein wenig länger (viele Jahre) und habe deswegen einen guten
Überblick diesbzgl..
> > Ich bin jetzt ein wenig müde über dieses Thema ... ;-)
> > wir sind uns einig:
> > "synchrone Sockets müssen nicht die UI blockieren".
> > Ich habe keine Einwände mehr.
>
> Habe auch keine Einwände mehr, nur 'ne klitzekleine Anmerkung
> wenn Du gestattest. Warum bist Du nie auf das LoadForm()
> Thema eingegangen? Sag mir doch ganz offen ob ich falsch
> liege oder richtig. Vergiss mal ganz die Socket-Thematik.
> Ist es guter Stil innnerhalb dieses events
> CPU-intensiven code (versprochen, ich fang jetzt nicht mehr
> wieder mit dem Wörtchen blo..ren an) unterzubringen?
Sagen wir so, tatsächlich schreibe ich viele Programme,
die im Form_Load etliche zeitintensive Dinge vornehmen.
Allerdings benutze ich folgendes Feature gerne:
private void Form1_Load(object sender, EventArgs e)
{
Cursor = Cursors.WaitCursor;
this.Show(); Application.DoEvents();
// DoLongLoad(...);
}
hat sich als geeigente Stelle erwiesen, wenn wirklich etwa
mal viele Daten mal unbedingt schon am Anfang geladen
werden sollen. Es gibt da viele Variationsmöglichkeiten (-
>Threading).
Das ist natürlich ein anderes Thema. Sollte also ggf.
in neuem Thread behandelt werden.
> Grüße und Danke für Deine Beteiligung auch nach EOT,
> war das jetzt wirklich so unfruchtbar? Ich finde nicht.
Wenn diese (80%) auf Verhalten bezogenen Postings
(wohl durch Misverständnisse) nicht gewesen wären,
hätten wir sicher jetzt noch richtig viel geschafft. Egal.
Danke auch für Deine Beteiligung.
> ciao Frank
> --
> Dipl.Inf. Frank Dzaebel [MCP/MVP C#]
> http://Dzaebel.NET
Hi Frank,
habe jetzt mal das vierte Beispiel runtergeladen und ausprobiert. Klar
dass da jetzt keine GUI mehr blockiert da sich FormLoad proper beenden kann.
Doch ob das Einrichten von Execute() und ReceiveHandler() wirklich
einfacher zu verstehen ist als die asynchronen Begin/End Funktionen?
Doch eines funktioniert an dem Beispiel nicht richtig, und das ist
folgendes:
// wenn der Client "" sendet, soll der Server beenden. (nur als Beispiel)
Wenn der Client aber "" sendet dann sollte er in diesem Falle nicht mehr
auf einen response des Servers warten und keinesfalls mehr Read()
aufrufen, es sei denn man implementiert noch dass der Server in diesem
Falle noch einen Abschiedsgruß an den Client sendet und sich für die
Session bedankt. ;-) Ansonsten hängt dann der Client im Read(), und dem
Client ist ja im Gegensatz zum Server kein thread hierfür spendiert
worden, der bleibt dann halt in der aufrufenden btnOK_Click() routine
hängen.
Es sollte also in etwa so geändert werden:
if (txtÜbertragungstext.Text.Length > 0)
{
tcpStream = tcpClient.GetStream();
UTF8Encoding encoding = new UTF8Encoding();
byte[] ba = encoding.GetBytes(txtÜbertragungstext.Text);
Melde("\r\nÜbertrage zum Server : \"" + txtÜbertragungstext.Text + "\"");
tcpStream.Write(ba, 0, ba.Length);
byte[] buffer = new byte[maxBuffer];
int gelesen = tcpStream.Read(buffer, 0, maxBuffer);
string empfangen = encoding.GetString(buffer, 0, gelesen);
Melde("Empfangen: \"" + empfangen + "\"");
}
else
{
tcpClient.Close();
}
Auf der Server-Seite sollte dann auch die Loop innerhalb Execute() vom
ReceiveHandler() aus beendet werden indem man den ResetEvent
signalisiert. In etwa so:
if (received == 0)
{
threadStopEvent.Set();
if (socket != null) socket.Close();
if (tcpListener != null) tcpListener.Stop();
Application.Exit(); return;
// wenn der Client "" sendet, soll der Server beenden. (nur als Beispiel)
}
ciao und happy weekend,
Peter
> Doch ob das Einrichten von Execute() und ReceiveHandler() wirklich
> einfacher zu verstehen ist als die asynchronen Begin/End Funktionen?
Für viele ist das sychrone Verfahren normal einfacher, ja
das ist meine Erfahrung über die Jahre.
Danach wird es ggf. noch in Threads gesteckt, wenn
das für das Handling wichtig ist.
Ich selber finde das auch sehr praktisch, gerade dieses
sukkzessive, aber darüber entscheide ich nicht, das
tuen die User. Du findest asynchrone einfacher - no prob.
Mein Beispiel lasse ich jetzt erstmal so, es soll erstmal
einfach gehalten werden.
Später werde ich wohl eher erstmal einen Decoder einbauen,
um mögliche Fragmentierung an Doppelbyte-Grenzen
zu vermeiden, es sind bereits von mir entsprechende
Links zu Implementierungsverfahren gepostet worden.
Gut - lass uns hier enden.
Synchrone Sockets brauchen die UI nicht einfrieren.
Danke für Dein Engagement.