Betrachten wir den folgenden Code

pollfd file_descriptors[1];
file_descriptors[0].fd = sock_fd;
file_descriptors[0].events = POLLIN;

int return_value = poll(file_descriptors, 1, 0);

if (return_value == -1) { cerr << strerror(errno); }
else if (return_value == 0) { cerr << "No data available to be read"; }
else { 
    if (file_descriptors[0].revents & POLLIN) {
        recv(sock_fd, buff, 1024, 0); 
    }
}

Jetzt habe ich zwei Fragen zum obigen Code.

  1. Wenn der Aufruf von poll () weder -1 noch 0 zurückgibt und das Flag POLLIN in der Bitmap revents für den ersten Eintrag im Array file_descriptors setzt, Wird dann der Aufruf von recv() blockiert? Wenn nein, werden die Daten dann sofort eingelesen?
  2. Angenommen, der Aufruf von poll() erfolgt auf die gleiche Weise wie oben erwähnt. Wie viele Daten werden eingelesen? Wird es nur das gleiche sein wie ein normaler Aufruf von recv()? d.h. ein beliebiger (für den Programmierer) Betrag, der im obigen Fall kleiner oder gleich 1024 ist. Wenn ich dann vor dem erneuten Lesen poll() möchte, wiederhole ich nur ab dem ersten Aufruf von poll(), bis alle Daten vollständig eingelesen wurden (dh in einem Client-Server-Szenario würde dies der Anforderung entsprechen abgeschlossen)?

Vielen Dank!

8
Curious 31 Dez. 2015 im 01:22

3 Antworten

Beste Antwort

Wenn der Aufruf von poll () weder -1 noch 0 zurückgibt und das POLLIN-Flag in den Bitmap-Revents für den ersten Eintrag im Array file_descriptors setzt, wird der Aufruf von recv () blockiert? Wenn nein, werden die Daten dann sofort eingelesen?

Der Aufruf von poll hat keine Auswirkung auf den Aufruf von recv. Ob recv blockiert ist oder nicht, hängt davon ab, welche Daten zum Zeitpunkt des Aufrufs von recv verfügbar sind und ob sich der Socket im blockierenden oder nicht blockierenden Modus befindet.

Angenommen, der Aufruf von poll () erfolgt auf die gleiche Weise wie oben erwähnt. Wie viele Daten werden eingelesen? Wird es nur das gleiche sein wie ein normaler Aufruf von recv ()? d.h. eine willkürliche (für den Programmierer) Menge, die im obigen Fall kleiner oder gleich 1024 ist. Wenn ich dann poll () vor dem erneuten Lesen abrufen möchte, wiederhole ich nur ab dem ersten Aufruf von poll (), bis alle Daten vollständig eingelesen wurden (d. H. In einem Client-Server-Szenario würde dies der abgeschlossenen Anforderung entsprechen)?

Angenommen, Sie möchten nicht blockieren, sollten Sie den Socket nicht blockieren. Sie haben zwei grundlegende Möglichkeiten. Sie können die Empfangsfunktion einmal und dann erneut poll aufrufen. Oder Sie können den Empfang so lange anrufen, bis Sie die Meldung "Blockieren" erhalten. Wenn es sich bei dem Socket um eine TCP-Verbindung handelt, können Sie die Empfangsfunktion so lange aufrufen, bis Sie entweder die Meldung "würde blockieren" erhalten oder weniger Bytes empfangen, als Sie angefordert haben.

Es gibt drei gängige, nicht blockierende E / A-Strategien, die auf poll oder select basieren können. Alle erfordern, dass die Steckdose nicht blockierend eingestellt ist.

1) Sie können jederzeit poll oder select aufrufen, bevor Sie eine E / A-Operation ausführen. Sie versuchen dann nur dann einen einzelnen Lese- oder Schreibvorgang, wenn Sie einen Lese- oder Schreibtreffer von poll oder select erhalten.

2) Sie können zuerst die Operation read oder write versuchen. Wenn es sofort gelingt, großartig. Wenn nicht, warten Sie auf einen Treffer von poll oder select, bevor Sie den Vorgang wiederholen.

3) Sie können poll oder select aufrufen, bevor Sie eine E / A-Operation ausführen. Sie versuchen dann mehrere read s oder write s, bis Sie entweder alles erledigen, was Sie tun müssen, oder eine "würde blockieren" -Anzeige erhalten. Wenn Sie die Anzeige "würde blockieren" erhalten, warten Sie, bis select oder poll Sie darüber informiert, bevor Sie eine weitere Operation in dieser Richtung an diesem Socket versuchen.

Methode 3 ist wahrscheinlich die häufigste Methode für Lesevorgänge. Methode 2 ist wahrscheinlich die häufigste Methode für Schreibvorgänge.

Es ist sehr wichtig zu beachten, dass poll eine Statusberichtsfunktion ist, die Ihnen aktuelle Informationen liefert. Es gibt keine zukünftigen Garantien. Die Annahme, dass eine Leseanzeige von poll bedeutet, dass eine zukünftige Leseoperation nicht blockiert wird, ist ein Fehler und hat in der Vergangenheit schwerwiegende Fehler mit erheblichen Auswirkungen auf die Sicherheit verursacht. Die einzige Möglichkeit, um sicherzustellen, dass eine Socket-Operation nicht blockiert, besteht darin, den Socket nicht zu blockieren.

2
David Schwartz 31 Dez. 2015 im 00:59

Wenn poll() einen streng positiven Wert zurückgibt, Dies bedeutet, dass mindestens einer Ihrer Deskriptoren einige Daten zurückgeben muss.

Das recv() SOLLTE daher nicht blockieren: as Es gibt Daten, die etwas zurückgeben sollten. In jedem Fall kann nicht garantiert werden, dass alle 1024 Bytes vom Aufruf zurückgegeben werden.

Sie müssen daher die Anzahl der von recv() zurückgegebenen Bytes überprüfen. Schließlich müssen Sie Ihre Abfrage / Ihren Empfang wiederholen, bis Sie alle erwarteten Daten erhalten haben.

Sie können das blockierende / nicht blockierende Verhalten entweder durch Aufrufen mit dem Flag-Parameter MSG_DONTWAIT oder über fcntl() dauerhafter steuern.

Bearbeiten: Beachten Sie, dass beispielsweise ein Verlust auftritt, wenn am Socket etwas schief geht () der Verbindung ) Die verfügbaren Daten, die von der Umfrage versprochen wurden, könnten verloren gehen und das recv() gegen alle Erwartungen blockieren. Es ist daher sicherer, das nicht blockierende Flag explizit zu verwenden (und zu berücksichtigen, dass recv() möglicherweise einen Fehlercode anstelle einer Anzahl gelesener Bytes zurückgibt).

1
Christophe 31 Dez. 2015 im 01:07

Wenn der Aufruf von poll() weder -1 noch 0 zurückgibt und das Flag POLLIN in der Bitmap-Version für den ersten Eintrag im Array file_descriptors setzt, wird der Aufruf von {{X3} ausgeführt } Block?

Dies sollte nicht der Fall sein, es sei denn, ein anderer Thread hat alle derzeit verfügbaren Daten aus dem Socket gelesen.

Wenn nein, werden die Daten dann sofort eingelesen?

Ja.

Angenommen, der Aufruf von poll() erfolgt auf die gleiche Weise wie oben erwähnt. Wie viele Daten werden eingelesen?

So viele Daten wie bereits eingetroffen.

Wird es nur das gleiche sein wie ein normaler Aufruf von recv()? d.h. eine willkürliche (für den Programmierer) Menge, die im obigen Fall kleiner oder gleich 1024 ist.

Ja.

Wenn ich dann vor dem erneuten Lesen poll() möchte, wiederhole ich nur ab dem ersten Aufruf von poll(), bis alle Daten vollständig eingelesen wurden (dh in einem Client-Server-Szenario würde dies der Anforderung entsprechen abgeschlossen)?

Ja.

0
Marquis of Lorne 31 Dez. 2015 im 00:58