Frage

Ich habe einen einfachen Multi-Threaded-Game-Server in Python geschrieben, das für jede Client-Verbindung einen neuen Thread erstellt. Ich finde, dass ab und zu, der Server wegen eines gebrochenen Rohr / SIGPIPE Fehler abstürzt. Ich bin mir ziemlich sicher, dass es geschieht, wenn das Programm versucht, eine Antwort zurück an einen Client zu senden, die nicht mehr vorhanden ist.

Was ist ein guter Weg, damit umzugehen? Meine bevorzugte Lösung wäre die serverseitige Verbindung zum Client und bewege auf einfach schließen, anstatt das gesamte Programm zu beenden.

PS: Diese Frage / Antwort befasst sich mit der Problem in allgemeiner Weise; wie gesagt sollte ich es lösen?

War es hilfreich?

Lösung

Lesen Sie oben auf dem Versuch:. Aussage

try:
    # do something
except socket.error, e:
    # A socket error
except IOError, e:
    if e.errno == errno.EPIPE:
        # EPIPE error
    else:
        # Other error

Andere Tipps

Unter der Annahme, dass Sie den Standard-Socket-Modul verwenden, sollten Sie die socket.error: (32, 'Broken pipe') Ausnahme seinen Fang (nicht IOError wie andere vorgeschlagen haben). Dies wird in dem Fall erhöht werden, die Sie beschrieben haben, das heißt das Senden / Schreiben an eine Steckdose für die die Remote-Seite getrennt wird.

import socket, errno, time

# setup socket to listen for incoming connections
s = socket.socket()
s.bind(('localhost', 1234))
s.listen(1)
remote, address = s.accept()

print "Got connection from: ", address

while 1:
    try:
        remote.send("message to peer\n")
        time.sleep(1)
    except socket.error, e:
        if isinstance(e.args, tuple):
            print "errno is %d" % e[0]
            if e[0] == errno.EPIPE:
               # remote peer disconnected
               print "Detected remote disconnect"
            else:
               # determine and handle different error
               pass
        else:
            print "socket error ", e
        remote.close()
        break
    except IOError, e:
        # Hmmm, Can IOError actually be raised by the socket module?
        print "Got IOError: ", e
        break

Beachten Sie, dass diese Ausnahme nicht immer auf den ersten Schreibvorgang in einer geschlossenen Buchse angehoben werden - mehr in der Regel die zweite Schreib (es sei denn, die Anzahl von Bytes in dem ersten Schreib geschrieben ist größer als die Puffergröße des Sockets). Sie müssen dies für den Fall im Auge behalten Ihre Anwendung denkt, dass das entfernte Ende die Daten aus dem ersten Schreib empfangen werden, wenn es möglicherweise bereits getrennt.

Sie können die Häufigkeit verringern (aber nicht vollständig beseitigen) dieses durch select.select() (oder poll) verwendet wird. Überprüfen Sie, ob Daten bereit, von dem Peer-zu lesen, bevor eine Schreib versuchen. Wenn select berichtet, dass es verfügbar ist, Daten aus dem Peer-Socket zu lesen, lesen sie socket.recv() verwenden. Wenn dies eine leere Zeichenfolge zurückgibt, hat die Gegenstelle die Verbindung geschlossen. Da es hier noch eine Race-Bedingung ist, werden Sie noch brauchen, um die Ausnahme zu fangen und zu behandeln.

Verdreht ist für diese Art der Sache, aber es klingt wie Sie bereits ein gutes Stück Code geschrieben hat.

SIGPIPE (obwohl ich denke, vielleicht meinen Sie EPIPE?) Auf Sockeln tritt auf, wenn Sie eine Steckdose heruntergefahren und dann Daten versenden. Die einfache Lösung ist nicht die Fassung zu beenden, bevor Sie versuchen, es Daten zu senden. Dies kann auch an Rohren passieren, aber es klingt nicht wie das ist, was Sie erlebt haben, da es sich um ein Netzwerk-Server ist.

Sie kann auch dann nur die Band-Aid, die Ausnahme in einigen Top-Level-Handler in jedem Thread zu fangen.

Natürlich, wenn Sie verwendet Verdrehte anstatt für jede Client-Verbindung einen neuen Thread Laichen, würde nicht Sie wahrscheinlich‘ t haben dieses Problem. Es ist wirklich schwer (vielleicht unmöglich, je nach Anwendung) die Reihenfolge der Nähe zu bekommen und Operationen korrekt schreiben, wenn mehrere Threads mit dem gleichen I / O-Kanal handeln.

Ich stehe mit der gleichen Frage. Aber ich den gleichen Code das nächste Mal einreichen, es funktioniert einfach. Das erste Mal, es brach:

$ packet_write_wait: Connection to 10.. port 22: Broken pipe

Das zweite Mal funktioniert es:

[1]   Done                    nohup python -u add_asc_dec.py > add2.log 2>&1

Ich denke, der Grund, über die aktuelle Server-Umgebung sein kann.

Meine Antwort ist ganz in der Nähe S.Lott ist, außer ich noch insbesondere sein würde:

try:
    # do something
except IOError, e:
    # ooops, check the attributes of e to see precisely what happened.
    if e.errno != 23:
        # I don't know how to handle this
        raise

, wobei „23“ ist die Fehlernummer, die Sie von EPIPE erhalten. Auf diese Weise werden Sie nicht einen Berechtigungsfehler oder etwas zu behandeln versuchen, sonst sind Sie nicht ausgerüstet.

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