Winsock: Was passiert, wenn man zu viel sendet?



  • Das wäre mir neu, wenn das passieren könnte. Die ganze trySendBuffer-Funktion ergibt für mich eigentlich keinen Sinn. Der IOCP wird AFAIK erst die Completion-Notification bekommen, wenn alle Daten (und nicht nur ein paar Daten) korrekt am Ziel angekommen sind (selbiges gilt auch für WSARecv()).



  • Jodocus schrieb:

    Das wäre mir neu, wenn das passieren könnte. Die ganze trySendBuffer-Funktion ergibt für mich eigentlich keinen Sinn. Der IOCP wird AFAIK erst die Completion-Notification bekommen, wenn alle Daten (und nicht nur ein paar Daten) korrekt am Ziel angekommen sind (selbiges gilt auch für WSARecv()).

    Tatsache, das scheint bei WSASend so zu sein, wusste ich nicht! Bei normalem send kann auch nur ein Teil gesendet werden.

    MSDN zu WSASend schrieb:

    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.

    MSDN zu send schrieb:

    On nonblocking stream oriented sockets, the number of bytes written can be between 1 and the requested length, depending on buffer availability on both the client and server computers.



  • MisterX schrieb:

    Belli schrieb:

    Blabla13443 schrieb:

    Ein send auf einem blockierenden Socket sendet alles oder nichts.

    Genau das ist falsch!

    Ich zitier mal aus der MSDN:

    If no buffer space is available within the transport system to hold the data to be transmitted, send will block unless the socket has been placed in nonblocking mode. On nonblocking stream oriented sockets, the number of bytes written can be between 1 and the requested length, depending on buffer availability on both the client and server computers.

    Du willst was über blockierende Sockets aussagen und bringst ein Zitat auch noch Fett geschrieben über nicht blockierende Sockets.

    Wenn da "only on nonblocking stream oriented sockets..." stehen würde, hätte es eine Aussagekraft... aber so sagt es rein nichts über blockierende Sockets aus.

    Für diejenigen, die nicht in der Lage sind, zu verstehen, was die MSDN damit sagen will, besteht ja noch die Möglichkeit, das auszutesten ...
    Wenn es Dir gelingt, unter Windows mit einem blockierenden Socket einen send auszuführen, der nur eine Teilmenge verschickt, melde Dich noch einmal mit einem entsprechenden nachvollziehbaren Beispiel.



  • fdfdg schrieb:

    MSDN zu WSASend schrieb:

    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.

    MSDN zu send schrieb:

    On nonblocking stream oriented sockets, the number of bytes written can be between 1 and the requested length, depending on buffer availability on both the client and server computers.

    Ähh, also hat das completion packet nun doch nix mit dem ACK vom Empfänger zu tun? Bekommt man es also, sobald die Daten transportiert wurden, und nicht erst, wenn der Empfänger empfangen hat? Dann würden die Pakete also auch verworfen (Irgendwo bei den Providern wohl) werden, könnte der Empfänger nicht schnell genug empfangen?!
    Dachte, das wäre nur bei UDP so.



  • Belli schrieb:

    MisterX schrieb:

    Belli schrieb:

    Blabla13443 schrieb:

    Ein send auf einem blockierenden Socket sendet alles oder nichts.

    Genau das ist falsch!

    Ich zitier mal aus der MSDN:

    If no buffer space is available within the transport system to hold the data to be transmitted, send will block unless the socket has been placed in nonblocking mode. On nonblocking stream oriented sockets, the number of bytes written can be between 1 and the requested length, depending on buffer availability on both the client and server computers.

    Du willst was über blockierende Sockets aussagen und bringst ein Zitat auch noch Fett geschrieben über nicht blockierende Sockets.

    Wenn da "only on nonblocking stream oriented sockets..." stehen würde, hätte es eine Aussagekraft... aber so sagt es rein nichts über blockierende Sockets aus.

    Für diejenigen, die nicht in der Lage sind, zu verstehen, was die MSDN damit sagen will, besteht ja noch die Möglichkeit, das auszutesten ...
    Wenn es Dir gelingt, unter Windows mit einem blockierenden Socket einen send auszuführen, der nur eine Teilmenge verschickt, melde Dich noch einmal mit einem entsprechenden nachvollziehbaren Beispiel.

    👍



  • Ich finde auch dass es nicht klar formuliert ist.
    Gemeint ist aber auf jeden Fall, dass auf blocking Stream Sockets immer alles versendet wird (so lange kein Fehler auftritt).



  • hustbaer schrieb:

    Ich finde auch dass es nicht klar formuliert ist.
    Gemeint ist aber auf jeden Fall, dass auf blocking Stream Sockets immer alles versendet wird (so lange kein Fehler auftritt).

    Dann guckst du mal!



  • hustbaer schrieb:

    Ich finde auch dass es nicht klar formuliert ist.

    Das ist es auch nicht. Noch unklarer formuliert ist meiner Meinung aber, dass bei einem recv möglicherweise nicht alles in einem Rutsch gelesen wird.



  • Kennt ihr denn nur MSDN?

    http://www.sockets.com/winsock2.htm das hier dürfte 50% der Fragen beantworten. MS-garbage ausgeschlossen.



  • Oh wow ... das ändert natürlich alles ...



  • Mit "completion packet" meinst du eine Benachrichtigung über einen IO Completion Port, oder? Falls nicht, vergiss den Rest der jetzt folgt.

    Hi schrieb:

    Ähh, also hat das completion packet nun doch nix mit dem ACK vom Empfänger zu tun?

    Richtig, hat es nicht. Macht auch Sinn. Sonst müsste man u.U. recht lange darauf warten.
    Du bekommst die Completion-Notification (über welchen Mechanismus auch immer) genau zu dem Zeitpunkt zu dem ein synchrones, blockierendes send() zurückkommen würde.
    Im Prinzip bedeutet dass nur, dass du deinen Sende-Puffer jetzt wieder freigeben/überschreiben darfst.

    Die Completion-Notification bedeutet nichtmal, dass die Daten schon versendet wurden. Die können zu dem Zeitpunkt noch in Puffern der Netzwerkkarte stehen. Bzw. sogar in Puffern des Betriebssystems, so dass noch nichtmal die Netzwerkkarte was davon mitbekommen hat.

    Anders wäre z.B. Send-Coalescing nicht möglich (siehe z.B. Nagle's Algorithm).

    Bekommt man es also, sobald die Daten transportiert wurden, und nicht erst, wenn der Empfänger empfangen hat?

    Nö, normalerweise sogar noch früher, siehe oben.

    Dann würden die Pakete also auch verworfen (Irgendwo bei den Providern wohl) werden, könnte der Empfänger nicht schnell genug empfangen?!

    Jain.

    Zu dem Zeitpunkt wo die Completion-Notification bekommst, ist nicht garantiert, dass der Empfänger die Daten bereits empfangen hat, oder jemals empfangen wird.
    Es ist allerdings garantiert, dass, WENN die Verbindung nicht abbricht, er die Daten irgendwann bekommen wird. Und zwar alle Daten, und auch genau in der Reihenfolge in der sie gesendet wurden.

    Dazu puffert der TCP/IP Stack vom Sender die Daten im RAM. Wenn die zu sendenden Daten auf dem Weg zum Epfänger ganz oder teilweise verloren gehen, dann sendet der TCP/IP Stack sie einfach nochmal. Und nochmal und nochmal, so lange bis alles angekommen ist. Das ganze passiert völlig transparent, d.h. du brauchst dich darum nicht zu kümmern. z.B. werden die Daten aus dem Puffer des Programms in einen Puffer des TCP/IP Stacks kopiert, bevor die Completion-Notification geschickt wird. Dadurch darfst das Programm "seinen" Puffer sofort nach der Completion-Notification überschreiben, ohne dass das "Neu-Versenden" von Daten dadurch beeinträchtigt wird.

    Und nochmal zu "könnte der Empfänger nicht schnell genug empfangen": der TCP/IP Stack des Senders puffert nur eine begrenzte Menge an Daten. Die Daten werden aus den internen Puffern des TCP/IP Stacks erst dann entfernt, wenn der Empfänger sie bestätigt hat (ACK). Daraus folgt, dass wenn der Sender schneller senden will als der Empfänger empfangen kann, send() irgendwann anfängt zu blockieren (bzw. die Completion-Notification erst später zu schicken). Anders gesagt: das System stellt sicher, dass du einfach nicht schneller senden kannst, als der Empfänger empfangen kann. Wenn du es versuchst, bremst es dich entsprechend aus.



  • Danke SEHR! 👍


Anmelden zum Antworten