FD_CLOSE vor FD_READ
-
Du musst auf jeden Fall um Dein recv noch eine while-Schleife drum rum machen, bis nix mehr empfangen werden kann!
Siehe die Dokzu zu WSASyncSelect:The WS2_32.DLL will not continually flood an application with messages for a particular network event. Having successfully posted notification of a particular event to an application window, no further message(s) for that network event will be posted to the application window until the application makes the function call that implicitly reenables notification of that network event.
D.h. Du musst alles mit recv zuerst auslesen, bevor Du wieder neue Nachrichten annehmen darfst, da sonst vielleicht ein FD_CLOSE kommt und Du noch nicht alle Daten gelesen hast.
Das wird vermutlich schon Dein Problem lösen...
-
PS: Auch solltest Du immer die Rückgabewerte von Funktionen testen!!!
-
Nein, auf ein FD_READ Nachricht sollte man nur einmal recv aufrufen.
With these semantics, an application need not read all available data in response to an FD_READ message — a single recv in response to each FD_READ message is appropriate.
-
Ähm, WSASyncSelect gibt es bei mir nicht, oder in welchem Paket ist das?
Ich benutzte bereite WSAAsyncSelect, aber das verursacht ja anscheinend das ganze Dilemma.
war das nur ein Tippfehler, oder woher bekomme ich die WSASyncSelect?
-
jo, Fipptehler vermutlich

Ich quote auch mal:
msdn schrieb:
FD_CLOSE should only be posted after all data is read from a socket, but an application should check for remaining data upon receipt of FD_CLOSE to avoid any possibility of losing data.
Be aware that the application will only receive an FD_CLOSE message to indicate closure of a virtual circuit, and only when all the received data has been read if this is a graceful close. It will not receive an FD_READ message to indicate this condition.
Hmm, einfach noch nen recv() vors WSACleanup()? - (Hmm, für gewöhnlich ruft man WSACleanup() erst am Programmende auf und WSAStartup() beim Programmstart? - Hast du nur eine Verbindung?)
-
hm, gute Idee, aber klappt nicht.
ich rufe WSAStartup() und WSACleanup() jedes mal auf, wenn ich ne neue Verbindung zum Server aufmache und das tu ich für jede seite einzeln.
wenn ich jetzt noch ein recv vor das WSACleanup() hänge bringt das nix, da er damit auch nur einen weiteren Teil der Daten bekommt, aber nicht alles, außerdem schmiert er ab, wenn keine Daten mehr da sein sollten.
ne was ich bräuchte wäre ne möglichkeit, die FD_CLOSE solange auszubremsen, bis wirklich alle FD_READ weg sind.
Ich wollte eigendlich schon mein WSAAsyncSelect() bebehalten, weil ich das ganz elegant find, aber wenn alles nix Hilft muss ich halt nochmal den ganzen Code umstellen.
-
......... schrieb:
Nein, auf ein FD_READ Nachricht sollte man nur einmal recv aufrufen.
With these semantics, an application need not read all available data in response to an FD_READ message — a single recv in response to each FD_READ message is appropriate.
Wenn aber anschliessend ein FD_CLOSE kommt, dann hast Du ein Problem...
Das Hauptproblem ist aber: Wenn Du ein recv mit Buffergröse von 1024 aufrufst und 2000 Bytes angekommen sind, so bleibt ein Teil übrig... dieser Teil kann schlimmstenfalls immer größer werden u´nd wird von Dir dann nich abgeholt.Ich kann nur dazu raten das recv so oft aufzurufen, bis weniger zurückkommt als der Buffer gross ist.
Es steht ja auch nicht da, dass es nicht erlaubt ist... ich mache es bei mir immer und es funktioniert tadelos...
-
Wie gesagt: Du musst auf FD_READ, das recv so oft in einer Schleife aufrufen, bis weniger zurückkommt, als der Bufer gross ist! Dann geht alles!
-
Das ist nicht nötig, wenn noch Daten da sind wird wieder eine FD_READ Nachricht generiert. Und genau deshalb sollte man es nur einmal aufrufen.
-
Ich habs jetzt mit der Holzhammermethode gelöst:
WSAAsyncSelect rausgenommen und ne einfache Schleife um recv gelegt.
Is zwar nicht elegant, funktioniert aber und scheint für meinen Zweck vollkommen ausreichend zu sein.
Danke nochmal für die Anregungen.
Wenn ich den Code posten soll sagt bescheid.
mfg
Ingenuus
-
Jochen Kalmbach schrieb:
Wie gesagt: Du musst auf FD_READ, das recv so oft in einer Schleife aufrufen, bis weniger zurückkommt, als der Bufer gross ist! Dann geht alles!
Laut msdn ist FD_READ da eine Ausnahme: Sobald recv() einmal aufgerufen wurde wird sofort im Anschluss geprüft ob immer noch was im Buffer ist und FD_READ erneut gesendet.
-
Habs nicht probiert... mag sein... schaden tut meine Implementierung auf jeden Fall auch nicht und baut nicht auf vermutungen die ich so nicht direkt eindeutig in der Doku lesen kann... oder wo steht es direkt eindeutig?
-
...steht ein bisschen weiter unten:
msdn schrieb:
Any call to the reenabling routine, even one that fails, results in reenabling of message posting for the relevant event.
For FD_READ, FD_OOB, and FD_ACCEPT events, message posting is level-triggered. This means that if the reenabling routine is called and the relevant condition is still met after the call, a WSAAsyncSelect message is posted to the application. This allows an application to be event-driven and not be concerned with the amount of data that arrives at any one time. Consider the following sequence:
- Network transport stack receives 100 bytes of data on socket s and causes Windows Sockets 2 to post an FD_READ message.
- The application issues recv( s, buffptr, 50, 0) to read 50 bytes.
- Another FD_READ message is posted because there is still data to be read.With these semantics, an application need not read all available data in response to an FD_READ message — a single recv in response to each FD_READ message is appropriate.
-
Super vielen Dank! Hab ich jetzt auch so nicht gewusst...
Danke für das Quoten (bin gerade im Urlaub und kann nicht so viel MSDN lesen
)