Frage

Der folgende Code funktioniert nicht richtig unter Windows (aber tut auf Linux):

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setblocking(True)
    sock.connect(address)
    gobject.io_add_watch(
            sock.fileno(),
            gobject.IO_OUT | gobject.IO_ERR | gobject.IO_HUP,
            callback)

Snippets von Kommentaren in verschiedenen Orten in der glib Quelle und anderen Orten erwähnt, dass in Windows Sockets in nicht-blockierenden während der Abfrage-Modus versetzt werden. Als Ergebnis wird der Rückruf self.outgoing_cb ständig genannt, und das Schreiben an die Steckdose nicht mit dieser Fehlermeldung:

[Errno 10035] A non-blocking socket operation could not be completed immediately

Beim sock.setblocking(True) vor dem Schreiben scheint nicht, dies zu umgehen. Durch die Absenkung der Priorität der Abfrage, und ignorieren Sie die Fehlermeldung, es funktioniert wie erwartet, aber wirft viel zu viele Ereignisse und verbraucht viel CPU. Gibt es eine Möglichkeit, um diese Einschränkung in Windows?

Aktualisieren

ich darauf hinweisen, könnte, dass der ganze Sinn der Abfrage für POLLOUT das ist, wenn Sie den Schreib machen rufen Sie nicht EAGAIN / EWOULDBLOCK bekommen. Die seltsame Fehlermeldung, die ich erhalte, ich glaube, die Windows-äquivalent wäre diese zwei Fehlercodes. Mit anderen Worten, ich bin immer gobject.IO_OUT Ereignisse, wenn die Buchse wird mich nicht erfolgreich lassen schreiben, und es Indienststellung Modus blockiert immer noch gibt mir dies nicht ausschließen Fehler.

Ein weiteres Update

Unter Linux, wo dies richtig funktioniert, ist der Sockel nicht auf nicht-blockierenden Modus geschaltet, und ich empfange IO_OUT, wenn die Buchse mich, ohne blockieren schreiben lassen, oder einen Fehler zu werfen. Es ist diese Funktionalität Ich möchte besten emulieren / Restore unter Windows.

Weitere Hinweise

Von man poll:

   poll()  performs a similar task to select(2): it waits for one of a set
   of file descriptors to become ready to perform I/O.
          POLLOUT
                 Writing now will not block.

Von man select:

A file descriptor  is considered ready if it is possible to perform the corre‐
sponding I/O operation (e.g., read(2)) without blocking.
War es hilfreich?

Lösung

Gibt es ein Problem mit dem Tun nicht blockierende E / A? Es scheint irgendwie seltsam Wahlkreise zu verwenden, wenn Sie E / A-Sperrung verwenden.

Wenn ich Programme wie dieses schreiben neige ich dazu folgendes zu tun:

  • die Bytes Puffer I auf den Dateideskriptor senden möchten.

  • Nur für IO_OUT fragen (oder poll() äquivalent, POLLOUT) Ereignisse, wenn der Puffer nicht leer ist.

  • Wenn poll() (oder gleichwertig) hat signalisiert, dass Sie bereit sind, die Schreib zu schreiben, auszustellen. Wenn Sie EAGAIN / EWOULDBLOCK erhalten, entfernen Sie das Bytes, die Sie erfolgreich aus dem Puffer geschrieben und wartet auf das nächste Mal, wenn Sie signalisiert bekommen. Wenn Sie erfolgreich den gesamten Puffer geschrieben hat, dann fragt nach POLLOUT stoppen, so dass Sie spuriously nicht aufwachen.

(Meine Vermutung ist, dass die Win32-Bindungen sind mit WSAEventSelect und WaitForMultipleObjects() zu simulieren poll(), aber das Ergebnis ist das gleiche ...)

Ich bin nicht sicher, wie Sie Ihren gewünschten Ansatz mit blockierende Sockets funktionieren würde. Sie sind „Aufwachen“ ständig, weil du dich zu wecken gefragt, wenn Sie schreiben können. Sie wollen nur, dass angeben, wenn Sie Daten zu schreiben ... Aber dann, wenn es Sie aufwacht, wird das System nicht wirklich sagen, Sie wie viel Daten, die Sie ohne blockieren schreiben können, so dass das, ein guter Grund, nicht blockierende E / a zu verwenden.

Andere Tipps

GIO enthält GSocket , ein "Low-Level-Netzwerk-Socket-Objekt" seit 2.22. Dies ist jedoch noch zu pygobject auf Windows portiert werden.

Ich bin nicht sicher, ob das hilft (I mit der Poll-Funktion oder den MFC-Sockets nicht bewandert bin und weiß nicht, die Abfrage eine Anforderung Ihrer Programmstruktur ist), so nehmen diese mit einem Körnchen Salz:

Aber eine blockierende oder EAGAIN auf Schreib zu vermeiden, verwenden wir wählen, dh die Buchse mit dem Schreibsatz hinzufügen, wählen übergeben wird, und wenn select () mit rc kommt zurück = 0 ist die Buchse wird schreibt sofort akzeptieren. ..

Die Schreibschleife wir in unserer App verwenden ist (in Pseudo-Code):

set_nonblocking.
count= 0.
do {
   FDSET writefds;
   add skt to writefds.
   call select with writefds and a reaonsable timeout.
   if (select fails with timeout) {
       die with some error;
   } 

   howmany= send(skt, buf+count, total-count).
   if (howmany>0) {
       count+= howmany.
   }
} while (howmany>0 && count<total);

könnten Sie verwenden Verdrehte , die Unterstützung für GTK (auch unter Windows) und wird alle verschiedene Fehlerbedingungen, die nicht-blockierende Sockets unter Windows wie zu erhöhen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top