Winsock: Was passiert, wenn man zu viel sendet?



  • Aber baut euch ruhig unsichere Programme. Ist ja nicht mein Problem.



  • Hi schrieb:

    Und irgendwann ist dann ein Puffer beim Sender voll... und dann? Crash?

    Nein, dann wartet das BS, bis er nicht mehr voll ist. Dann wird weiter gesendet. Ob blockierend oder nicht.



  • Aber wie soll man darauf reagieren...
    zB. man will 1 GB versenden; Sendet mit 3 MB/sec. Empfänger hat aber 56k Einwahl. Und man sendet, und sendet, und sendet... und wo stapeln sich die inzwischen zB. fast 500 versendeten MB (Von denen der Empfänger zB. erst 1 MB erhalten hat)? Und wenn es mehr werden? Was passiert und was soll man (die Anwendung) dann tun?



  • Solange Du TCP und blockierende Sockets nutzt solltest Du dich nicht darum kümmern müssen.
    Teste es doch einfach mal - sende (übers Netz(!)) schneller als jemand empfangen kann, und guck was passiert 😉



  • Ich möchte aber IOCP verwenden.



  • Hi schrieb:

    Aber wie soll man darauf reagieren...
    zB. man will 1 GB versenden; Sendet mit 3 MB/sec. Empfänger hat aber 56k Einwahl. Und man sendet, und sendet, und sendet... und wo stapeln sich die inzwischen zB. fast 500 versendeten MB (Von denen der Empfänger zB. erst 1 MB erhalten hat)? Und wenn es mehr werden? Was passiert und was soll man (die Anwendung) dann tun?

    Versuchen wir es mal darzustellen:

    Sender hat 3 mpbs, Empfänger hat 56 kbps. Sowohl Sender- als auch Empfängerpuffer seien 1 MB groß.

    Ausgansgsituation: Beide Puffer leer, du willst 1 GB senden
    Beim Senden haut das BS von dem GB das erste MB in den Sendepuffer und stößt bei der unterliegenden Schicht das Senden an. Die Pakete werden zum Empfänger geschickt, dank TCP läuft der Empfangspuffer auch nicht über. Dein Programm läuft ja wegen asynch weiter und sobald das eine MB verschickt ist, triggered dein IOCP und du kannst wieder was in den Sendepuffer schieben. Also das nächste Stück von dem GB.

    Das heißt, du musst die Daten vorhalten. In deinem Beispiel mit den versendeten 500 MB von denen der Empfänger erst ein MB erhalten hat, gäbe es gar keine versendeten 500 MB. Einfach, weil das BS nur immer ein bisschen von dem GB in den Sendepuffer übernimmt, nicht gleich 500 MB. Es gäbe also nur 1 versendetes MB, welches im Sendepuffer darauf wartet, verschickt zu werden. Die restlichen 1023 MB hältst du in deinen Datenstrukturen vor.



  • Hmm, ich hatte mir das anders vorgestellt:
    Ich dachte, man würde gleich alles senden, weil es ja nicht blockiert. Also einfach so oft WSASend() aufrufen, bis alle Daten weg sind, sei es 1 GB.

    Da kommt eine weitere Frage auf: Wie viel darf ich einem WSASend()-Aufruf maximal auf einmal übergeben? Könnte ich auch 1 GB mit einem einzigen Aufruf senden? Soll man das machen? Wie geht man bei WSASend()+overlapped überhaupt vor?



  • Hi schrieb:

    Wie viel darf ich einem WSASend()-Aufruf maximal auf einmal übergeben? Könnte ich auch 1 GB mit einem einzigen Aufruf senden? Soll man das machen? Wie geht man bei WSASend()+overlapped überhaupt vor?

    Ich würde es etwa so machen:

    // Datenquelle, hier einfach mal ein einfacher Puffer
    std::vector<char> Buffer;
    
    // Rufen wir von unserem IOCP-System auf, wenn was gesendet wurde
    void trySendBuffer( int BytesSent, bool Error ) {
        if ( Error )
            ; // TODO
        // Sicherheitshalber...
        assert( BytesSent>0 && BytesSent<=Buffer.size() );
        // Was gesendet wurde aus dem Puffer löschen
        Buffer.erase( Buffer.begin(), Buffer.begin()+BytesSent );
        // Nächstes Stück senden
        IOCP.send( &Buffer[0], Buffer.size(), trySendBuffer );
    }
    
    // Um das ganze anzustoßen:
    IOCP.send( &Buffer[0], Buffer.size(), trySendBuffer );
    


  • Einfach anstoßen... Habs kapiert. Ist ja voll easy 🙄



  • Das scheint doch ziemlich sinnlos, wenn man die volle Puffergröße angibt.

    BytesSent wird dann eh gleich Buffer.size() sein, wenn kein Fehler aufgetreten ist.



  • hmmmmmm schrieb:

    BytesSent wird dann eh gleich Buffer.size() sein, wenn kein Fehler aufgetreten ist.

    Meistens und gerade für kleine Größen: Ja. Für auch nur halbwegs ernsthafte Anwendungen darf man aber die unwahrhscheinlichen Fälle nicht außer Acht lassen.



  • 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.


Anmelden zum Antworten