Fehler: Adresse wird bereits verwendet, während Socket mit Adresse verbunden wird, aber die Portnummer wird von `netstat` frei angezeigt
Lesezeit: 5 Minuten
Durin
Ich habe versucht, meinen Socket (Server-Socket) an die Portnummer zu binden 8000. Es hat funktioniert und die Arbeit für mich erledigt. Am Ende des Codes schließe ich auch den Socket. Im nächsten Moment führe ich meinen Code erneut aus und er zeigt mir, dass die Adresse bereits verwendet wird. Ich habe die Bedeutung der Fehlerwerte gedruckt strerror(errno); um zu sehen, ob mein Code an jedem Punkt richtig funktioniert. Um zu überprüfen, ob der Port frei ist, habe ich ihn mit überprüft netstat aber es zeigt diese Portnummer 8000 ist gratis. Es ist mir schon oft passiert. Jedes Mal warte ich dann noch ein paar Sekunden und dann funktioniert es wieder. Ich verwende C-Sprache. Was ist der Grund für dieses Verhalten meines Betriebssystems?
Nach ein paar Sekunden führe ich den Code aus und dann funktioniert es.
[email protected]:~/Desktop/testing$ sudo ./a.out
Socket Creation: Success
File open: Success
Socket Bind: Address already in use
Socket Listen: Address already in use
^C
[email protected]:~/Desktop/testing$ sudo netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1348/lighttpd
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 984/sshd
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 1131/cupsd
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 1211/mysqld
tcp6 0 0 :::22 :::* LISTEN 984/sshd
tcp6 0 0 ::1:631 :::* LISTEN 1131/cupsd
[email protected]:~/Desktop/testing$ sudo ./a.out
Socket Creation: Success
File open: Success
Socket Bind: Address already in use
Socket Listen: Address already in use
^C
[email protected]:~/Desktop/testing$
Schließen Sie auch sorgfältig alle Verbindungen, die während des Betriebs zum Server hergestellt wurden?
– Rogerpack
11. Oktober 2018 um 19:45 Uhr
icfantv
Ich bin auch auf das gleiche Problem gestoßen. Das liegt daran, dass Sie Ihre Verbindung zum Socket schließen, aber nicht den Socket selbst. Der Socket kann in einen TIME_WAIT-Zustand eintreten (um sicherzustellen, dass alle Daten übertragen wurden, garantiert TCP die Lieferung, wenn möglich) und es dauert bis zu 4 Minuten, um loszulassen.
Es ist sicherlich ärgerlich, aber es ist kein Fehler. Siehe den Kommentar von @Vereb zu dieser Antwort unten zur Verwendung von SO_REUSEADDR.
Auf der von Ihnen verlinkten Seite finden Sie eine mögliche Lösung. Sie können die Option SO_REUSEADDR für den Socket verwenden. siehe Setsockopt hier: linux.die.net/man/3/setsockopt
– Verb
27. Januar 2013 um 14:30 Uhr
Supami
Ich weiß, es ist eine Weile her, seit die Frage gestellt wurde, aber ich konnte eine Lösung finden:
int sockfd;
int option = 1;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
Damit ist der Sockel sofort wiederverwendbar.
Ich entschuldige mich, wenn das “falsch” ist. Ich bin nicht sehr erfahren mit Steckdosen
Ich mag, wie Sie setzen wrong in Anführungszeichen, was bedeutet, dass jeder, der nicht Ihrer Meinung ist, falsch liegt.
– byxor
8. Februar 2017 um 11:29 Uhr
Die Anführungszeichen waren eher eine Art “Wenn es funktioniert, ist es nicht falsch”. Mir ist klar, dass dies wahrscheinlich nicht der bevorzugte Weg ist, und wenn jemand den “richtigen” Weg kennt, wäre ich daran interessiert zu hören.
– Supami
27. März 2017 um 14:30 Uhr
was bedeutet die 1
– Moritz Schmidt
13. August 2018 um 7:22 Uhr
Es ist eine Weile her, also wenn ich falsch liege, korrigieren Sie mich bitte, aber ich glaube, das wird verwendet, denn wenn Sie möchten, dass der Socket nicht verweilt, muss er “nicht Null” sein. Ich konnte nichts Konkretes finden, aber Sie können mehr darüber lesen unter: ibm.com/support/knowledgecenter/en/SSB23S_1.1.0.15/gtpc2/…
– Supami
13. August 2018 um 14:01 Uhr
Versuchen Sie netstat wie folgt: netstat -ntpohne das -l. Es zeigt die TCP-Verbindung an TIME_WAIT Zustand.
Wie schon gesagt, da kommt wohl deine Steckdose rein TIME_WAIT Zustand. Dieses Problem ist gut beschrieben von Thomas A. Guthier.
Zusammenfassend folgt der Schließvorgang des Sockets dem folgenden Diagramm:
Thomas sagt:
Wenn man sich das obige Diagramm ansieht, wird das deutlich TIME_WAIT kann vermieden werden, wenn das entfernte Ende die Schließung einleitet. So kann der Server Probleme vermeiden, indem er den Client zuerst schließen lässt. Das Anwendungsprotokoll muss so gestaltet sein, dass der Client weiß, wann er schließen muss. Der Server kann als Reaktion auf ein EOF vom Client sicher schließen, muss jedoch auch eine Zeitüberschreitung festlegen, wenn er ein EOF erwartet, falls der Client das Netzwerk unsanft verlassen hat. In vielen Fällen reicht es aus, einfach ein paar Sekunden zu warten, bevor der Server schließt.
Verwenden SO_REUSEADDR wird allgemein im Internet vorgeschlagen, aber Thomas hinzufügen:
Seltsamerweise mit SO_REUSEADDR kann tatsächlich zu schwierigeren “Adresse wird bereits verwendet”-Fehlern führen. SO_REUSADDR ermöglicht es Ihnen, einen Port zu verwenden, der feststeckt TIME_WAIT, aber Sie können diesen Port immer noch nicht verwenden, um eine Verbindung zum letzten Ort herzustellen, mit dem er verbunden war. Was? Angenommen, ich wähle den lokalen Port 1010 und verbinde mich mit foobar.com Port 300 und schließe dann lokal, wobei ich diesen Port belasse TIME_WAIT. Ich kann den lokalen Port 1010 sofort wiederverwenden, um eine Verbindung zu überall herzustellen, außer zu foobar.com Port 300.
Programmierer
Tipp einfach
unlink [SOCKET NAME]
im Terminal, dann sollte der Fehler nicht mehr vorhanden sein.
Das ist für Unix-Domain-Sockets. Die Frage bezieht sich auf TCP-Sockets.
– Benutzer207421
1. Juli 2020 um 0:54 Uhr
Uhr ZHONG
Auch die Antwort von icfantv auf diese Frage ist bereits perfekt, ich habe noch weitere Erkenntnisse in meinem Test.
Als Server-Socket im Abhörstatus, wenn er nur im Abhörstatus ist, und sogar Anfragen akzeptiert und Daten von der Clientseite erhält, jedoch ohne Datensendeaktion. Wir könnten den Server immer noch sofort neu starten, nachdem er gestoppt wurde. Wenn jedoch auf der Serverseite eine Aktion zum Senden von Daten an den Client erfolgt, wird beim Neustart des gleichen Dienstes (gleicher Port) dieser Fehler angezeigt: (Adresse wird bereits verwendet).
Ich denke, dass dies durch die TCP/IP-Designprinzipien verursacht wird. Wenn der Server die Daten an den Client zurücksendet, muss sichergestellt werden, dass das Senden der Daten erfolgreich ist. Dazu muss das Betriebssystem (Linux) die Verbindung überwachen, auch wenn die Serveranwendung diesen Socket geschlossen hat. Aber ich glaube immer noch, dass der Kernel-Socket-Designer dieses Problem verbessern könnte.
Das ist für Unix-Domain-Sockets. Die Frage bezieht sich auf TCP-Sockets.
– Benutzer207421
1. Juli 2020 um 0:54 Uhr
dr_begemot
Für AF_UNIX können Sie call unlink (path) verwenden; nach dem close()-Socket in der “Server”-App
14167300cookie-checkFehler: Adresse wird bereits verwendet, während Socket mit Adresse verbunden wird, aber die Portnummer wird von `netstat` frei angezeigtyes
Schließen Sie auch sorgfältig alle Verbindungen, die während des Betriebs zum Server hergestellt wurden?
– Rogerpack
11. Oktober 2018 um 19:45 Uhr