2016-09-21 3 views
1

Ich habe einen 'Jobs' Server, der Anfragen von einem Client akzeptiert (es gibt 8 Clients, die Anfragen von einem anderen Rechner senden). Der Server sendet dann einen 'Job' (ein 'Job' ist nur eine ausführbare Datei, die eine Ergebnisdatei auf die Festplatte schreibt), und auf einem 'Job-Manager' wartet der Thread, bis der Job beendet ist. Wenn ein Job fertig ist, sendet er eine Nachricht an den Client, dass eine Ergebnisdatei bereit ist, zurück auf den Client kopiert zu werden.lesbare socket mal auf recv

Auf dem Haupt-Thread ich select eingehende Verbindungen von Clients, um zu lesen, sowie Jobs Anfragen:

readable, writable, exceptional = select.select(inputs, [], []) 

wo inputs eine Liste der akzeptierten Verbindungen (Sockets) ist, und diese Liste enthält auch die server Steckdose. Alle Sockets sind auf nicht blockierend eingestellt. Nach meinem besten Verständnis, wenn dieser Aufruf an select eine nicht leere readable zurückgibt, bedeutet dies, dass einige Elemente von inputs eingehende Daten warten, um gelesen zu werden. I-Daten am Lesen der folgenden Logik (SIZE ist eine Konstante):

for s in readable: 
    if s is not server: 
     try: 
      socket_ok = True 
      data = s.recv(SIZE) 
     except socket.error as e:   
      print ('ERROR socket error: ' + str(e)) 
      socket_ok = False 
     except Exception as e: 
      print ('ERROR error reading from socket: ' + str(e)) 
      socket_ok = False 
     if not socket_ok: 
      # do something 

Ich habe 2 Probleme:

  • Manchmal habe ich eine [Errno 110] Connection timed out Ausnahme, und ich verstehe nicht, warum - wenn Ich habe eine lesbare Steckdose, heißt das nicht, dass einige Daten gelesen werden müssen?
  • Wie mit dieser Ausnahme umgehen - die #do something Teil. Ich kann eine Bereinigung durchführen - lösche die laufenden Jobs, die vom Timeout-Socket angefordert wurden, und entferne den toten Socket aus der Liste. Aber ich habe keine Möglichkeit, den Kunden wissen zu lassen, dass er aufhören sollte, auf die Ergebnisse dieser Jobs zu warten. Idealerweise möchte ich mich irgendwie wieder verbinden, denn die Jobs selbst laufen weiter und bringen Ergebnisse hervor, die ich nicht wegwerfen möchte.

EDIT Ich erkennen nun, dass der Manager Jobs Thread hat auch Zugang zu den Buchsen über eine Queue Instanz - wenn ein Auftrag abgeschlossen ist, sendet der Thread eine Meldung über die entsprechende Buchse ‚Job gemacht‘ - so vielleicht die send und recv Methoden der gleichen Buchse verursachen eine Art Race Condition? Aber ich sehe sowieso nicht, dass dies zu einem 'Verbindungsfehler' führen kann.

+0

Versuchen Sie, die Details hier zu lesen: https://pymotw.com/2/select/ –

+0

@ ReutSharabani, ich lese es und tatsächlich basiert mein Code darauf. Aber Sie können in meinem Code sehen, dass die Ausnahme beim Lesen von einem Socket in der "readbale" -Liste ausgelöst wird, und der Link, den Sie erwähnten, besagt, dass "alle Sockets in der lesbaren Liste eingehende Daten gepuffert und zum Lesen verfügbar sind" Das erklärt also nicht das Problem, das ich habe –

Antwort

0

Eine Lösung, die nur eine Vermutung war und zu funktionieren scheint: Auf der Client-Seite verwende ich eine blockierende recv Methode, um Nachricht vom Server zu erhalten, dass der Job erledigt ist. Da ein Job sehr lange dauern kann (z. B. wenn der Cluster, auf dem die Jobs ausgeführt werden, nur wenig Ressourcen zur Verfügung hat), vermutete ich, dass der wartende Socket möglicherweise die Ursache für das Timeout war. Anstatt also recv im Blockiermodus zu verwenden, verwende ich es mit einer Zeitüberschreitung von 5 Sekunden, so dass ich alle 5 Sekunden eine Dummy-Nachricht an den Server senden kann, um die Verbindung aufrecht zu erhalten, bis eine Nachricht empfangen wird. Jetzt bekomme ich die Ausnahme (auf der Serverseite) nicht mehr.