Sie sollten die folgenden Schritte für eine asynchrone Verbindung verwenden:
- Socket erstellen mit
socket(..., SOCK_NONBLOCK, ...)
- Verbindung starten mit
connect(fd, ...)
- wenn der Rückgabewert weder
0
ist nochEINPROGRESS
, dann mit Fehler abbrechen - warten Sie bis
fd
als ausgabebereit gemeldet - Überprüfen Sie den Status des Sockets mit
getsockopt(fd, SOL_SOCKET, SO_ERROR, ...)
- erledigt
Keine Schleifen - es sei denn, Sie möchten mit EINTR
umgehen .
Wenn der Client zuerst gestartet wird, sollten Sie den Fehler ECONNREFUSED
sehen im letzten Schritt. Schließen Sie in diesem Fall den Socket und beginnen Sie von vorne.
Es ist schwierig zu sagen, was mit Ihrem Code nicht stimmt, ohne weitere Details zu sehen. Ich nehme an, dass Sie bei Fehlern in Ihrem check_socket
nicht abbrechen Betrieb.
Es gibt verschiedene Möglichkeiten, um zu testen, ob eine nicht blockierende Verbindung erfolgreich ist.
- rufen Sie zuerst getpeername() auf, wenn es mit dem Fehler ENOTCONN fehlgeschlagen ist, ist die Verbindung fehlgeschlagen. Rufen Sie dann getsockopt mit SO_ERROR auf, um den anstehenden Fehler auf dem Socket abzurufen
- rufen Sie read mit einer Länge von 0 auf. Wenn das Lesen fehlgeschlagen ist, ist die Verbindung fehlgeschlagen, und die Fehlernummer für read gibt an, warum die Verbindung fehlgeschlagen ist; read gibt 0 zurück, wenn die Verbindung erfolgreich ist
- Verbindung erneut anrufen; Wenn die Fehlernummer EISCONN lautet, ist die Verbindung bereits hergestellt und die erste Verbindung erfolgreich.
Ref:UNIX-Netzwerkprogrammierung V1
D. J. Bernstein hat verschiedene Methoden zusammengestellt, wie man prüfen kann, ob ein asynchroner connect()
vorliegt Anruf erfolgreich oder nicht. Viele dieser Methoden haben auf bestimmten Systemen Nachteile, daher ist das Schreiben von portablem Code dafür unerwartet schwierig. Wenn jemand alle möglichen Methoden und ihre Nachteile lesen möchte, lesen Sie dieses Dokument.
Für diejenigen, die nur die tl;dr-Version wollen, ist der portabelste Weg der folgende:
Sobald das System den Socket als beschreibbar signalisiert, rufen Sie zuerst getpeername()
auf um zu sehen, ob es verbunden ist oder nicht. Wenn dieser Aufruf erfolgreich war, wurde der Socket verbunden und Sie können ihn verwenden. Wenn dieser Aufruf mit ENOTCONN
fehlschlägt , die Verbindung ist fehlgeschlagen. Um herauszufinden, warum es fehlgeschlagen ist, versuchen Sie, ein Byte aus dem Socket read(fd, &ch, 1)
zu lesen , was ebenfalls fehlschlagen wird, aber der Fehler, den Sie erhalten, ist der Fehler, den Sie von connect()
erhalten hätten wenn es nicht nicht blockierend wäre.