Warum wird recv erst blockiert, wenn alle Daten empfangen wurden?

8

Warum blockiert der recv Systemaufruf nicht, bis alle Daten empfangen wurden? Jedes Mal, wenn ich einen recv -Aufruf gesehen habe, befindet es sich in einer while-Schleife, die solange recv aufruft, bis alle Daten vorhanden sind. Warum nicht einfach recv an erster Stelle blockieren?

    
jasonbogd 09.01.2012, 03:20
quelle

3 Antworten

9

Sie können diesen Recv-Block anfordern, bis alle Daten empfangen wurden, mit dem MSG_WAITALL -Flag. Wenn jedoch ein Signal eintrifft, kann ein Systemaufruf, der eine gewisse Arbeit ausgeführt hat (dh einen Teil der Daten empfängt) nicht automatisch neu gestartet werden, um den Rest zu empfangen. Daher gibt es auch Fälle mit MSG_WAITALL , in denen der Recv-Aufruf möglicherweise zurückkehrt, bevor der Puffer voll ist, und Sie müssen bereit sein, diese Fälle zu behandeln. Angesichts dieser Tatsache entscheiden sich viele Leute einfach für eine Schleife und kümmern sich nicht um wenig bekannte Flags wie MSG_WAITALL .

Warum dies der Fall ist, gibt es einige Gründe, die Ihnen in den Sinn kommen:

  • Häufig möchten Sie Teillesungen erhalten. Wenn Sie beispielsweise die eingehenden Daten inkrementell anzeigen oder wenn Sie sie an anderer Stelle als Proxy verwenden, oder wenn die Daten nur so groß sind, können Sie die gesamte Datei nicht gleichzeitig im Speicher zwischenspeichern. Wenn Sie nur sofort in eine Datei schreiben, ist es wichtig, dass Sie sie auf 200 Schreibvorgänge aufteilen, statt auf 150?
  • Manchmal wissen Sie nicht einmal, wie viele Daten Sie am Anfang benötigen. Betrachten Sie das telnet -Protokoll, das zu der Zeit populär war, als die BSD Sockets API entworfen wurde. Normalerweise erhalten Sie nur eine Handvoll Bytes gleichzeitig. Es gibt keine Längenfelder, die Ihnen sagen, wie viele Daten zu erwarten sind, und außerdem müssen Sie diese Daten sofort anzeigen . Es macht keinen Sinn zu blockieren, bis Sie hier einen Puffer füllen. Ebenso bei leitungsorientierten Protokollen wie SMTP oder IMAP - Sie wissen nicht, wie lange der Befehl dauert, bis Sie alles empfangen haben.
  • recv wird oft für Datagrammsockets verwendet, wo es ein einzelnes Datagramm empfängt, auch wenn es viel kleiner ist als der bereitgestellte Puffer. Die natürliche Erweiterung zu Streaming-Sockets ist, so viel wie möglich zurückzugeben, ohne zu warten.

Aber am wichtigsten ist, dass Sie, wenn Sie bereit sein müssen, mit einem partiellen Puffer umzugehen auf jeden Fall , Leute dazu zwingen, standardmäßig damit umzugehen, damit sie die Fehler in ihrer Schleife frühzeitig aufdecken - anstatt dass sie sich verstecken, bis ein Signal zu einem unglücklichen Moment kommt.

    
bdonlan 09.01.2012 03:25
quelle
4

In den meisten Fällen wissen Sie nicht, wie viele Daten "alle Daten" sind. Wenn Sie beispielsweise Daten in einem zeilenorientierten Protokoll empfangen, kann eine Zeile 10 Byte lang oder 65 Byte lang sein.

    
David Schwartz 09.01.2012 03:26
quelle
2

Sie können Socket-Flags entweder in blockierend oder nicht blockierend ändern. Ihr spezifischer Fall hat tatsächlich nichts mit dem Blockieren oder Nicht-Blockieren zu tun.

Es würde keinen Sinn machen, wenn eine Netzwerkfunktion sich so verhält, wie Sie es standardmäßig beschreiben - was ist, wenn der Stream nie endet ... Sollte das Programm niemals enden? Prima facia, das scheint nicht gesund Standard Verhalten.

Lesen Sie Ссылка , um sich mit blockierenden und nicht blockierenden IOs vertraut zu machen.

    
David Titarenco 09.01.2012 03:26
quelle