Servus,
es zickt schon wieder ;)
Ubuntu 21, Gnu C-Compiler.
1
staticints;
2
staticstructsockaddr_ina,a1;
3
staticintport=8001;
4
5
s=socket(AF_INET,SOCK_STREAM,0);
6
memset(&a,0,sizeof(a));
7
a.sin_family=AF_INET;
8
a.sin_port=htons(port);
9
a.sin_addr.s_addr=htonl(INADDR_ANY);
10
11
bind(s,(structsockaddr*)&a,sizeof(a));
12
listen(s,100);
13
printf("\nlistening on port %d, PID %d",port,getpid());
14
fflush(stdout);
Symptome:
Meist lauscht es an Port 8001, manchmal nicht. Lt. lsof -i
lauscht es an einem anderen, beliebigen Port zB 37041 oÄ.
Nach mehrmaligem Abbruch mit ^C geht es dann wieder eine Weile.
Was kann denn das sein ?
Joachim D. schrieb:> Bisher> 20 Versuche, immer 0 und der Port stimmt. 8001 ist frei.
Starte Dein Tool mal testweise doppelt, damit der Port schon belegt ist.
Es dürfte davon abhängen, wie eine Verbindung beendet wird. Wird sie
nicht vollständig beendet, beispielsweise bei Abbruch/Crash des Servers,
bleibt der Socket im System auch nach Ende des Servers noch eine Weile
im Status TIME_WAIT hängen und der Port ist währenddessen nicht
benutzbar. Fehlt dir die Geduld, das abzuwarten, dann probier es mit
SO_REUSEADDR/SO_REUSEPORT.
Hmmm schrieb:> Starte Dein Tool mal testweise doppelt, damit der Port schon belegt ist.
http-Server jdcc uQuery Linux, build Apr 11 2022 / 13:29:19 bind -1
*** Fehler Address already in use listen 0
listening on port 8001, PID 6471
(prx) A. K. schrieb:> Fehlt dir die Geduld, das abzuwarten, dann probier es mit> SO_REUSEADDR/SO_REUSEPORT.
Ersteres reicht und ist POSIX-konform.
Joachim D. schrieb:> Address already in use
Genau das dürfte vorher auch passiert sein, da bloss noch unbemerkt.
Joachim D. schrieb:> Wieso bleibt der socket offen wenn das Programm beendet> wird ? Normal schließt das OS ja alles Ressourcen ...
Wenn bei der Beendigung noch eine Verbindung zu einem Client besteht,
muss die nach allen Regeln des TCP korrekt beendet werden. Beendet der
Client die Verbindung, gehts schnell. Tut es der Server, dann nicht:
https://hea-www.harvard.edu/~fine/Tech/addrinuse.html
Joachim D. schrieb:> Wieso bleibt der socket offen wenn das Programm beendet> wird ? Normal schließt das OS ja alles Ressourcen ...
Der Socket wird aus Userland-Sicht geschlossen, aber der TCP/IP-Stack
hat ggf. noch eine Weile mit den Verbindungen zu tun.
Stell Dir z.B. einen Mobilfunk-Client vor, der durch einen Netzabriss
nicht auf das FIN reagiert.
Kölner schrieb:> SOCK_STREAM wird nicht sofort mit Beendigung des Programms geschlossen.> Versuchs mal mit SOCK_DGRAM.
SOCK_DGRAM ist in diesem Fall UDP, das will man nur selten wirklich.
Aber SO_REUSEADDR ist genau für solche Fälle da: Solange kein listen()
läuft, bekommt man den Port zurück.
Joachim D. schrieb:> Was könnte das sein ? Port 8001 taucht da nicht auf.
Mit was hast du nachgeschaut?
Mit "netstat" siehst du da z.B.
1
tcp 0 0 localhost:8001 localhost:57438 TIME_WAIT
und solange da noch ein oder mehrere "TIME_WAIT"-TCP-Verbindungen
hängen, kriegst du den Serverport nicht zurück. Außer mit SO_REUSEADDR,
das ist exakt dafür da.
Joachim D. schrieb:> Was könnte das sein ? Port 8001 taucht da nicht auf.
Mit was hast du nachgeschaut?
Mit "netstat" siehst du da z.B.
1
tcp 0 0 localhost:8001 localhost:57438 TIME_WAIT
und solange da noch ein oder mehrere "TIME_WAIT"-TCP-Verbindungen
hängen, kriegst du den Serverport nicht zurück. Außer mit SO_REUSEADDR,
das ist exakt dafür da.
Joachim D. schrieb:> Es dauert> ca 2 min dann ist der Port wieder frei.
# cat /proc/sys/net/ipv4/tcp_fin_timeout
Aber: diesen Wert runterzustellen lindert nur die Symptome, "repariert"
kriegst du es mit
int flagvalue = 1;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &flagvalue, sizeof(int));
habe ich eingebaut. Mal sehen ob sich etwas tut ;)
Vielen Dank an alle !
Joachim D. schrieb:> Es dauert> ca 2 min dann ist der Port wieder frei.
Also genau das Verhalten, das prx und ich mit Hinweis auf SO_REUSEADDR
beschrieben haben.
Joachim D. schrieb:> lsof -i
Das bringt nichts, der Socket existiert ja mangels Prozess nicht mehr.
netstat -a hätte Dir den Grund gezeigt.
Joachim D. schrieb:> Mal sehen ob sich etwas tut ;)
Du kannst das einfach provozieren, indem Du bei bestehender
TCP-Connection den Ethernet-Stecker der Gegenstelle rausziehst.
Εrnst B. schrieb:> Aber: diesen Wert runterzustellen lindert nur die Symptome, "repariert"> kriegst du es mit
Ich möchte nochmal anmerken, dass das nicht den Fehler behebt, sondern
einen work-around darstellt. Der Fehler ist immer noch, dass ein Socket
nicht ordnungsgemäß geschlossen wurde.
Hmmm schrieb:> netstat -a hätte Dir den Grund gezeigt.
Ich verwende dafür immer netstat -tulpn