Frage

Ich habe ein ganz einfaches Problem hier. Ich muß mit vielen Hosts gleichzeitig kommunizieren, aber ich brauche eigentlich keine Synchronisation, da jede Anfrage ziemlich autark ist.

Aus diesem Grund entschied ich mich mit asynchronen Sockets zu arbeiten, anstatt Threads Spamming. Jetzt habe ich ein kleines Problem:

Die Asynchron-Sachen wie ein Zauber funktioniert, aber wenn ich zu 100 Hosts zu verbinden, und ich bekomme 100 Timeouts (Timeout = 10 Sekunden), dann warte ich 1000 Sekunden, nur um herauszufinden, alle meine Verbindungen fehlgeschlagen.

Gibt es eine Möglichkeit auch nicht blockierenden Socket Connects zu bekommen? Meine Buchse ist bereits auf nicht-blockierenden, fordert jedoch () zu verbinden blockiert noch.

das Timeout zu reduzieren, ist keine akzeptable Lösung.

ich dies in Python tue, aber ich denke, die Programmiersprache tut in diesem Fall wirklich wichtig ist.

Muss ich wirklich Threads verwenden?

War es hilfreich?

Lösung

Sie müssen die Verbindung herstellt und parallelisieren, da die Steckdosen sperren, wenn Sie ein Timeout. Alternativ könnten Sie nicht ein Timeout gesetzt, und das Auswahlmodul verwenden.

Sie können dies tun, mit der Dispatcher-Klasse in der asyncore Modul . Werfen Sie einen Blick auf die grundlegenden http-Client Beispiel . Mehrere Instanzen dieser Klasse werden sie beim Verbinden nicht blockieren. Sie können dies genauso einfach Threads, und ich denke, macht Tracking-Buchse Timeouts einfacher, aber da Sie bereits asynchrone Methoden können Sie auch auf der gleichen Spur bleiben.

Als Beispiel folgende Arbeiten auf allen meinen Linux-Systemen

import asyncore, socket

class client(asyncore.dispatcher):
    def __init__(self, host):
        self.host = host
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect((host, 22))

    def handle_connect(self):
        print 'Connected to', self.host

    def handle_close(self):
        self.close()

    def handle_write(self):
        self.send('')

    def handle_read(self):
        print ' ', self.recv(1024)

clients = []
for i in range(50, 100):
    clients.append(client('cluster%d' % i))

asyncore.loop()

Wo in cluster50 - cluster100 gibt es zahlreiche Maschinen, die nicht mehr reagiert, oder gar nicht vorhanden sind. Dieser beginnt sofort Druck:

Connected to cluster50
  SSH-2.0-OpenSSH_4.3

Connected to cluster51
  SSH-2.0-OpenSSH_4.3

Connected to cluster52
  SSH-2.0-OpenSSH_4.3

Connected to cluster60
  SSH-2.0-OpenSSH_4.3

Connected to cluster61
  SSH-2.0-OpenSSH_4.3

...

Dies dauert jedoch nicht berücksichtigt Getaddrinfo, die zu blockieren hat. Wenn Sie Fragen sind mit den DNS-Abfragen zu lösen, hat alles zu warten. Sie müssen wahrscheinlich die DNS-Abfragen separat auf eigene Faust, sammeln und die IP-Adressen in Ihrem Asynchron-Schleife verwenden,

Wenn Sie einen größeren Toolkit als asyncore wollen, werfen Sie einen Blick auf Twisted-Matrix . Es ist ein bisschen schwer zu bekommen, aber es ist die beste Netzwerk-Programmier-Toolkit Sie für Python bekommen.

Andere Tipps

Mit dem select Modul. Auf diese Weise können Sie für E / A-Abschluss auf mehrere nicht-blockierende Sockets warten. Hier einige weitere Informationen zu ausgewählten . Von der verlinkten Seite:

  

In C select Codierung ist ziemlich komplex.   In Python, es ist ein Stück Kuchen, aber   es ist nahe genug an der C-Version   dass, wenn Sie verstehen, wählen Sie in   Python, werden Sie keine Probleme haben,   mit ihm in C.

ready_to_read, ready_to_write, in_error = select.select(
                  potential_readers, 
                  potential_writers, 
                  potential_errs, 
                  timeout)
  

Sie übergeben select drei Listen: die erste   alle Steckdosen enthält, die Sie vielleicht   wollen versuchen, zu lesen; die zweit alle   die Buchsen möchten Sie vielleicht versuchen,   Schreiben auf, und die letzte (normalerweise   links leer) diejenigen, die Sie wollen   auf Fehler prüfen. Sie sollten beachten, dass   eine Buchse kann mehr als einen gehen in   Liste. Der select Aufruf blockiert, aber   Sie können es ein Timeout geben. Das ist   im Allgemeinen eine vernünftige Sache zu tun -   geben ihm einen schönen langen Timeout (sagen wir ein   Minute), es sei denn Sie haben guten Grund zu   sonst tun.

     

Im Gegenzug werden Sie drei Listen erhalten.   Sie haben die Steckdosen, die   tatsächlich lesbar, beschreibbar und in   Error. Jede dieser Listen ist eine Teilmenge   (Möglicherweise leere) des entsprechenden   Liste, die Sie übergeben. Und wenn Sie ein setzen   Buchse in mehr als eine Eingabeliste, es   wird nur (höchstens) wird in einer Ausgabe   Liste.

     

Wenn eine Buchse ist in der Ausgabe lesbar   Liste können Sie sein   as-close-to-sicher-als-wir-immer-man-in-diesem-Business   dass ein recv auf diesem Sockel zurückkehren   etwas. Gleiche Idee für die beschreibbaren   Liste. Sie werden in der Lage zu send   etwas. Vielleicht nicht alles, was Sie wollen,   aber etwas ist besser als nichts.   (Eigentlich jeder einigermaßen gesund   Buchse wird als beschreibbar zurückkehren - es   bedeutet nur, ausgehende Netzwerkpuffer   Platz zur Verfügung steht.)

     

Wenn Sie einen „Server“ Buchse haben, setzen Sie es   in der potential_readers Liste. Wenn es   kommt in der lesbaren Liste verschicken,   akzeptieren (fast sicher) Arbeit.   Wenn Sie einen neuen Socket erstellt   eine Verbindung zu einem anderen Person, steckt es in dem   potential_writers Liste. Wenn es zeigt sich   in der beschreibbaren Liste, Sie haben ein   gute Chance, dass es angeschlossen ist.

Leider gibt es kein Beispiel-Code, der den Fehler zeigt, so ist es ein bisschen schwer zu sehen, wo dieser Block kommt.

Er tut so etwas wie:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setblocking(0)
s.connect(("www.nonexistingname.org", 80))

Das Socket-Modul verwendet intern Getaddrinfo, die ein blockierende Betrieb ist, vor allem, wenn der Hostname existiert nicht. Ein Standard-konformes DNS-Client wird noch einige Zeit warten, um zu sehen, ob der Name wirklich existiert nicht, oder wenn es nur einig langsamer DNS-Server beteiligt ist.

Die Lösung ist die Verbindung nur zu-IP-Adressen oder DNS-Client verwenden, die nicht blockierende Anfragen erlaubt, wie pydns .

Verwenden Sie verdrehten .

Es ist ein asynchrones Networking-Engine in Python geschrieben, zahlreiche Protokolle unterstützt, und Sie können Ihre eigenen hinzufügen. Es kann verwendet werden, Clients und Server zu entwickeln. Es blockiert nicht auf verbinden.

Haben schauen Sie auf der asyncore Modul? Könnte sein, was Sie brauchen.

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