2013-12-09 7 views
5

Diese Frage ist nicht auf Python beschränkt. Es ist eine allgemeine Socket-Frage. Ich habe einen nicht blockierenden Socket und möchte eine Verbindung zu einem Rechner herstellen, der erreichbar ist - auf der anderen Seite existiert der Port nicht. Warum funktioniert select (...) überhaupt? Ich habe eine Auszeit erwartet. sock.send (...) scheitert mit einem kaputten Rohr. Wie kann ich nach Auswahl von (...) feststellen, ob der Socket wirklich verbunden ist? Vielen Dank im Voraus.Nicht blockierende Verbindung

import socket, errno, os, time, select 

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sock.setblocking(0) 
err = sock.connect_ex(('192.168.178.21', 12345)) 
ready_to_read, ready_to_write, in_error = select.select([], [sock], [], timeout=5) 
#ready_to_write is set even 192.168.178.21:12345 does not exist. 

sock.setblocking(1) 
sock.send('foo') #this fails 
sock.close() 

Antwort

4

Versuchen Sie, die Rückgabewerte zu überprüfen. Hier ist, was ich in einer ähnlichen Situation kommen:

>>> import socket, errno, os, time, select 
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
>>> sock.setblocking(0) 
>>> err = sock.connect_ex(('10.0.0.1', 12345)) 
>>> import errno 
>>> print errno.errorcode[err] 
EINPROGRESS 
>>> print sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) 
61 
>>> print errno.errorcode[61] 
ECONNREFUSED 

Der select() Anruf wahrscheinlich zurückkehrt, weil es ein außergewöhnlicher Zustand auf dem Sockel war - das heißt, die Verbindung verweigert wurde.

Wenn ich das tue, die select() kehrt sofort:

>>> ready_to_read, ready_to_write, in_error = select.select([], [sock], []) 

Und interessanterweise passen die Rückgabewerte genau das, was Sie übergeben (wenn Sie mehr als eine Buchse hatte, das wäre wahrscheinlich anders sein):

>>> print in_error 
[] 
>>> print ready_to_read 
[] 
>>> print ready_to_write 
[<socket._socketobject object at 0x10ccd0980>] 

die Designer von select() erwarten Sie select() in einer Schleife zu laufen, und wenn ein Socket einen Fehler zurückzugibt, wenn Sie die Schreib versuchen, entfernen Sie sie aus der Liste, wenn der Schreib ausfällt.

So haben Sie ein paar Optionen, aus der Spitze von meinem Kopf:

  • Warten Sie, bis Sie versuchen, den Sockel zu lesen und versagen, dann die entsprechenden Maßnahmen ergreifen.
  • Verwenden Sie getsockopt() wie oben, um zu überprüfen, ob der Socket in Ordnung ist oder in einem Fehlerzustand ist, bevor Sie versuchen, irgendetwas damit zu tun.
+0

sock.getsockopt (socket.SOL_SOCKET, socket.SO_ERROR) hat den Trick für mich getan. – HelloWorld

+1

ok. Denken Sie daran, dass der Socket zwischen dem Zurücksetzen von 'getsockopt()' und Ihrem Versuch, den Socket zu lesen oder zu schreiben, heruntergefahren werden könnte. Sie sollten also versuchen, Fehler bei send/recv korrekt zu behandeln. – mpontillo

Verwandte Themen