it-swarm.com.de

Fehler: Adresse wird bereits verwendet, während der Socket mit der Adresse gebunden wird, die Portnummer wird jedoch von netstat frei angezeigt

Ich habe versucht, meinen Socket (Server-Socket) an Portnummer 8000 zu binden. Es hat funktioniert und die Arbeit für mich erledigt. Am Ende des Codes schließe ich auch die Steckdose. Schon beim nächsten Mal führe ich meinen Code erneut aus und es zeigt mir, dass die Adresse bereits verwendet wird. Ich habe die Bedeutung der Fehlerwerte strerror(errno); ausgedruckt, um zu sehen, ob mein Code an jedem Punkt ordnungsgemäß funktioniert. Um zu überprüfen, ob der Port frei ist, habe ich ihn mit netstat geprüft, aber die Portnummer 8000 ist frei. Bei mir ist es oft passiert. Ich warte jedes Mal ein paar Sekunden und dann geht es wieder los. 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$ 
47
Durin

Ich bin auch in die gleiche Frage geraten. Dies liegt daran, dass Sie die Verbindung zum Sockel schließen, nicht jedoch den Sockel. Der Socket kann in den Status TIME_WAIT wechseln (um sicherzustellen, dass alle Daten übertragen wurden, garantiert TCP die Zustellung wenn möglich) und es dauert bis zu 4 Minuten, bis freigegeben wird.

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

Es kann ärgerlich sein, um sicher zu sein, aber es gibt keinen richtigen Weg und es ist kein Fehler.

50
icfantv

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 die Steckdose sofort wieder verwendbar.

Ich entschuldige mich, wenn dies "falsch" ist. Ich bin nicht sehr erfahren mit Steckdosen 

20
Supamee

Versuchen Sie netstat wie folgt: netstat -ntp, ohne -l. Es zeigt die TCP-Verbindung im TIME_WAIT-Zustand.

18
hipe

Wie bereits erwähnt, ist Ihr Sockel wahrscheinlich im TIME_WAIT-Zustand. Dieses Problem wird von Thomas A. Finehier beschrieben.

Um es zusammenzufassen, folgen Sie dem nachstehenden Diagramm:

 Socket closing process

Thomas sagt:

Wenn Sie das Diagramm oben betrachten, ist es klar, dass TIME_WAIT .__ sein kann. vermieden, wenn das entfernte Ende die Schließung einleitet. So kann der Server Vermeiden Sie Probleme, indem Sie den Client zuerst schließen. Die Anwendung Das Protokoll muss so ausgelegt sein, dass der Client weiß, wann geschlossen werden soll. Das Der Server kann jedoch sicher als Antwort auf ein EOF vom Client geschlossen werden Es muss auch ein Timeout festgelegt werden, wenn im Fall .__ ein EOF erwartet wird. Der Client hat das Netzwerk ungekünstelt verlassen. In vielen Fällen einfach Warten einige Sekunden, bevor der Server geschlossen wird, ist ausreichend.

Die Verwendung von SO_REUSEADDR wird häufig im Internet vorgeschlagen, aber Thomas fügt hinzu:

Seltsamerweise kann die Verwendung von SO_REUSEADDR tatsächlich zu schwierigeren Fehlern bei der "Adresse Bereits verwendet" führen. Mit SO_REUSADDR können Sie einen Port verwenden, der .__ ist. in TIME_WAIT stecken, aber Sie können diesen Port immer noch nicht verwenden, um eine .__ zu erstellen. Verbindung mit dem letzten Ort, an dem es verbunden ist. Was? Angenommen, ich wähle lokaler Port 1010 und stellen Sie eine Verbindung zu foobar.com-Port 300 her, und schließen Sie dann lokal, den Port in TIME_WAIT belassen. Ich kann den lokalen Port 1010 .__ wiederverwenden. sofort für Verbindungen mit foobar.com port 300.

6
Jezz

Schreib einfach

unlink [SOCKET NAME]

im terminal sollte dann der fehler nicht mehr existieren.

5
programmer

Selbst die Antwort von icfantv auf diese Frage ist bereits perfekt, ich habe noch weitere Ergebnisse in meinem Test.

Als Server-Socket im Abhörstatus, wenn er nur im Abhörstatus ist und sogar Anforderungen akzeptiert und Daten von der Clientseite abruft, jedoch ohne das Senden von Daten. Wir könnten den Server trotzdem sofort neu starten, nachdem er gestoppt wurde. Wenn jedoch auf der Serverseite Daten an den Client gesendet werden, wird beim Neustart desselben Diensts (gleicher Port) folgender Fehler angezeigt: (Adresse wird bereits verwendet).

Ich denke, das liegt an den TCP/IP-Designprinzipien. Wenn der Server die Daten an den Client zurücksendet, muss er sicherstellen, dass das Senden der Daten erfolgreich ist. Dazu muss das Betriebssystem (Linux) die Verbindung überwachen, auch wenn die Serveranwendung diesen Socket geschlossen hat .. __ Ich glaube trotzdem, Kernel-Socket Designer könnte dieses Problem verbessern.

1
Clock ZHONG

der Fehler, den ich erhielt, war:

cockpit.socket: Failed to listen on sockets: Address already in use

das Update, das ich entdeckte, ist:

  1. Ich musste Selinux deaktivieren
  2. in/usr/lib/systemd/system/cockpit-Dienst habe ich die -Zeile geändert:

    #ExecStartPre=/usr/sbin/remotectl certificate --ensure --user=root --group=cockpit-ws --selinux-type=etc_t
    

    zu:

    #ExecStartPre=/usr/sbin/remotectl certificate --ensure --user=root --group=cockpit-ws 
    

wie Sie sehen, habe ich das Argument über Selinux herausgenommen. Dann lief ich:

systemctl daemon-reload
systemctl start cockpit.service

dann habe ich gesucht:

Ich akzeptierte das selbstsignierte Zertifikat und konnte sich erfolgreich im Cockpit anmelden und es normal verwenden.

dies ist alles auf einer Fedora25-Maschine. Der 9090-Port wurde bereits mit firewall-cmd hinzugefügt.

0
JamesAD-0

Für AF_UNIX können Sie call unlink (path) verwenden. nach close () Socket in der "Server" -App

0
dr_begemot