Fehler: Adresse wird bereits verwendet, während Socket mit Adresse verbunden wird, aber die Portnummer wird von `netstat` frei angezeigt

Lesezeit: 5 Minuten

Benutzeravatar von Durin
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

Benutzeravatar von icfantv
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.

oder, für eine WIRKLICH detaillierte/technische Erklärung, überprüfen Sie diesen Link

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

Benutzeravatar von Supamee
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. Gut hier.

Zusammenfassend folgt der Schließvorgang des Sockets dem folgenden Diagramm:

Socket-Schließvorgang

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.

Benutzeravatar des Programmierers
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

Takten Sie den Benutzeravatar von ZHONG
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

Benutzeravatar von dr_begemot
dr_begemot

Für AF_UNIX können Sie call unlink (path) verwenden; nach dem close()-Socket in der “Server”-App

1416730cookie-checkFehler: Adresse wird bereits verwendet, während Socket mit Adresse verbunden wird, aber die Portnummer wird von `netstat` frei angezeigt

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy