IOCP und partielles WSASend (TCP)
-
Hi!
Ich hab mal wieder was zu IOCP gelesen, und traf bei einem Thema leider auf geteilte Meinungen: Partielles WSASend() bei TCP.
> Was soll man tun, wenn mehrere WSASend ausstehend sind, und nun das erste WSASend() zurückkehrt (completion), aber vom übergebenen Buffer nicht alle Bytes gesendet wurden?
Eigentlich wollte ich dann in der completion ein weiteres WSASend posten, mit den verbleibenden Daten des ersten WSASend()-Aufrufs.
Doch das ist angeblich problematisch: Während der completion könnte der Kernel doch schon beginnen, ein weiteres, ausstehendes WSASend() zu bearbeiten, sendet also Daten davon und _danach_ komme ich und sende in der completion noch Reste vom buffer aus dem 1. WSASend()-Aufruf.
Somit kommt der Stream durcheinander.Doch dann lese ich an mehreren Stellen, dass zumindest die Windows-Implementierung bei overlapped gar keine partiellen sends zulässt.
So schön es wäre, muss ich mich doch fragen: Kann das wirklich sein? Was, wenn ich WSASend() einen Megagroßen buffer übergebe, zb. 100MB. Kommt die completion dann erst, wenn diese 100MB verschickt wurden?
Das mag ich nicht so recht glauben.
Andererseits würden partielle sends doch das asynchrone Design zerstören?! (Weil dann immer nur ein WSASend() ausstehend sein dürfte)
-
In der MSDN steht: "A completion indication will occur, invoking the completion of a routine or setting of an event object, when the buffer(s) have been consumed by the transport."
Ist es in deinem Programm überhaupt schon mal vorgekommen, dass WSASend() nicht alle Bytes verschickt hat und trotzdem completet? Warum testes du es nicht einfach mal mit einem riesigen Puffer?
-
Ahaa sehr interessant. Hab mal 1GB in einem WSASend() über Lan verschickt.
SO_SNDBUF auf 0: Die completion kommt scheinbar erst, wenn die Empfangsseite alles bestätigt hat! (Der buffer ist ja auch nur im userspace)
SO_SNDBUF default: Die completion kommt gleich, mit 1GB transferred. Der buffer im userspace kann gelöscht werden, doch der GB steckt dann so lange im kernel nonpaged, bis die Empfangsseite alles hat oder beendet.Ich glaube, SO_SNDBUF auf 0 ist besser (Bei overlapped natürlich).
-
Mist, hier http://www.mofeel.net/40-microsoft-public-win32-programmer-networks/291.aspx sagt jemand (Alexander Nickolov, Microsoft MVP [VC], MCSD), dass gerade bei SO_SNDBUF auf 0 partielle sends möglich sind.
-
Weiß noch jemand was?
Ich möchte unbedingt SO_SNDBUF auf 0 setzen, denn dann weiß ich direkt, dass bei einer completion die Daten von der Empfängerseite bestätigt wurden. Das benötige ich für einen anwendungsspezifischen flow control.
Die Frage bleibt, ob es immer alle Daten sind, oder ob es nun doch ein partielles WSASend() gibt... wäre allerdings fatal, anwendungsdesigntechnisch...