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?
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:
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.
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.
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.
Tags und Links python c sockets network-programming