Überprüfen Sie diesen Link
http://www.toptip.ca/2010/02/linux-eaddrnotavail-address-not.html
BEARBEITEN :Ja, ich wollte mehr hinzufügen, musste es aber wegen eines Notfalls kürzen
Haben Sie den Socket geschlossen, bevor Sie erneut versucht haben, eine Verbindung herzustellen? Das Schließen teilt dem System mit, dass das Socketpaar (IP/Port) jetzt frei ist.
Hier sind weitere Elemente, die Sie sich ansehen sollten:
- Wenn der lokale Port bereits mit der angegebenen Remote-IP und dem Port verbunden ist (d. h. es gibt bereits ein identisches Socket-Paar), erhalten Sie diesen Fehler (siehe Fehlerlink unten).
- Das Binden einer Socket-Adresse, die nicht die lokale ist, erzeugt diesen Fehler. wenn die IP-Adressen einer Maschine 127.0.0.1 und 1.2.3.4 sind und Sie versuchen, sich an 1.2.3.5 zu binden, erhalten Sie diesen Fehler.
- EADDRNOTAVAIL:Die angegebene Adresse ist auf dem Remote-Rechner nicht verfügbar oder das Adressfeld der Namensstruktur besteht ausschließlich aus Nullen.
Link mit einem ähnlichen Fehler wie Ihrem (Antwort steht ganz unten)
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4294599
Es scheint, dass Ihr Socket im Wesentlichen in einem der internen TCP-Zustände feststeckt und dass das Hinzufügen einer Verzögerung für die Wiederverbindung Ihr Problem lösen könnte, wie es in diesem Fehlerbericht anscheinend der Fall war.
Wenn Sie die Anzahl der verfügbaren temporären Ports nicht ändern möchten (wie von David vorgeschlagen) oder mehr Verbindungen als das theoretische Maximum benötigen, gibt es zwei andere Methoden, um die Anzahl der verwendeten Ports zu reduzieren. Sie verstoßen jedoch in unterschiedlichem Maße gegen den TCP-Standard und sollten daher mit Vorsicht verwendet werden.
Die erste besteht darin, SO_LINGER
einzuschalten mit einem Timeout von null Sekunden, wodurch TCP
erzwungen wird Stack, um ein RST-Paket zu senden und den Verbindungsstatus zu löschen. Es gibt jedoch eine Feinheit:Sie sollten shutdown
aufrufen auf dem Socket-Dateideskriptor vor Ihnen close
, damit Sie die Möglichkeit haben, einen FIN
zu senden Paket vor dem RST
Paket. Der Code sieht also etwa so aus:
shutdown(fd, SHUT_RDWR);
struct linger linger;
linger.l_onoff = 1;
linger.l_linger = 0;
// todo: test for error
setsockopt(fd, SOL_SOCKET, SO_LINGER,
(char *) &linger, sizeof(linger));
close(fd);
Der Server sollte nur dann einen vorzeitigen Verbindungs-Reset sehen, wenn FIN
Paket wird mit dem RST
neu geordnet Paket.
Weitere Einzelheiten finden Sie unter TCP-Option SO_LINGER (Null) – wenn erforderlich. (Experimentell scheint es keine Rolle zu spielen, wo Sie setsockopt
setzen .)
Die zweite ist die Verwendung von SO_REUSEADDR
und ein expliziter bind
(auch wenn Sie der Client sind), wodurch Linux temporäre Ports wiederverwenden kann, wenn Sie ausgeführt werden, bevor sie mit dem Warten fertig sind. Beachten Sie, dass Sie müssen Verwenden Sie bind
mit INADDR_ANY
und Port 0
, sonst SO_REUSEADDR
wird nicht respektiert. Ihr Code sieht in etwa so aus:
int opts = 1;
// todo: test for error
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
(char *) &opts, sizeof(int));
struct sockaddr_in listen_addr;
listen_addr.sin_family = AF_INET;
listen_addr.sin_port = 0;
listen_addr.sin_addr.s_addr = INADDR_ANY;
// todo: test for error
bind(fd, (struct sockaddr *) &listen_addr, sizeof(listen_addr));
// todo: test for addr
// saddr is the struct sockaddr_in you're connecting to
connect(fd, (struct sockaddr *) &saddr, sizeof(saddr));
Diese Option ist weniger gut, da Sie immer noch die internen Kernel-Datenstrukturen für TCP-Verbindungen gemäß netstat -an | grep -e tcp -e udp | wc -l
sättigen . Sie werden Ports jedoch erst dann wiederverwenden, wenn dies geschieht.
Dies kann auch passieren, wenn ein ungültiger Port angegeben wird, z. B. 0.