Windows Azure Cloud Storage ermöglicht es Ihnen bereits ab 0,10€ pro GB/Monat die Vorteile der Cloud zu nutzen.
Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.de  
   
Advanced Developers Conference     
Bücher-Shop mit Amazon (Buchkategorien)C++ : Referenzen zu C++ : C++ Builder : Visual C++ : C# : Java : Spieleprogrammierung : Systemprogrammierung Linux : Software-Entwicklung : .NET : Compilertechnik : Algorithmen & Datenstrukturen : Objektorientierung : Entwurfsmuster : UML : eXtreme Programming : Scrum : Projektmanagement : Software-Testing : Datenbanken : Tom DeMarco : Dilbert : User Friendly
C/C++ Forum :: FAQ - Linux/Unix ::  Port auch nach Absturz besetzt  
Gehen Sie zu Seite 1, 2  Weiter
  Zeige alle Beiträge auf einer Seite
Auf Beitrag antworten
Autor Nachricht
hackbert
Mitglied

Benutzerprofil
Anmeldungsdatum: 03.11.2001
Beiträge: 723
Beitrag hackbert Mitglied 16:23:52 28.10.2004   Titel:   Port auch nach Absturz besetzt            Zitieren

Ich habe eine Anwendung geschrieben, die auf Port 4000 lauscht. Nun enthält das Programm irgendwo einen Fehler und wenn ich einen Client verbinde stürzt die Anwendung ab. Allerdings bleibt der Port besetzt. Die Anwendung ist nicht mehr aktiv, sie ist beendet (Zumindest sagt ps -A das). Wenn ich dann die Anwendung erneut starte kann kein Port erstellt werden, weil er angeblich schon besetzt ist. Nach einiger Zeit kann ich das Programm allerdings wieder starten (schwer reproduzierbar, weiß nicht genau wie lange es dauert).

Ich führe das Programm mit ganz normalen Benutzerrechten aus, nicht als root. Das System ist ein SuSE 9.0 mit Kernel 2.4.21.243-athlon

_________________
http://www.programmierforen.de | KernelWiki


Zuletzt bearbeitet von hackbert am 16:24:05 28.10.2004, insgesamt 1-mal bearbeitet
Werbeunterbrechung
wischmop2
Mitglied

Benutzerprofil
Anmeldungsdatum: 04.05.2001
Beiträge: 127
Beitrag wischmop2 Mitglied 17:13:26 28.10.2004   Titel:              Zitieren

jep, "normaler Weise" ist so! Mach's deshalb so:

C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  struct sockaddr_in a_sockaddr;
  int sock;
  // Unverbundenen Socket erzeugen
  if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
    perror("(socket) ");
    return;
  }
  int opt = 1;
  if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) == -1) {
    perror("(setsockopt) ");
    return;
  }
  a_sockaddr.sin_family      = AF_INET;
  a_sockaddr.sin_port        = htons(4000);
  a_sockaddr.sin_addr.s_addr = INADDR_ANY;
  // Adresse mit Socket binden
  if (bind(sock, (struct sockaddr*) &a_sockaddr, sizeof(struct sockaddr_in)) == -1) {
    perror("(bind) ");
    return;
  }
  // Neue Verbindungen annehmen
  if(listen(sock, SOMAXCONN) == -1) {
    perror("(listen) ");
    return;
  }
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
struct sockaddr_in a_sockaddr;
int sock;
// Unverbundenen Socket erzeugen
if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
perror("(socket) ");
return;
}
int opt = 1;
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) == -1) {
perror("(setsockopt) ");
return;
}
a_sockaddr.sin_family = AF_INET;
a_sockaddr.sin_port = htons(4000);
a_sockaddr.sin_addr.s_addr = INADDR_ANY;
// Adresse mit Socket binden
if (bind(sock, (struct sockaddr*) &a_sockaddr, sizeof(struct sockaddr_in)) == -1) {
perror("(bind) ");
return;
}
// Neue Verbindungen annehmen
if(listen(sock, SOMAXCONN) == -1) {
perror("(listen) ");
return;
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  struct sockaddr_in a_sockaddr;
  int sock;
  // Unverbundenen Socket erzeugen
  if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
    perror("(socket) ");
    return;
  }
  int opt = 1;
  if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) == -1) {
    perror("(setsockopt) ");
    return;
  }
  a_sockaddr.sin_family      = AF_INET;
  a_sockaddr.sin_port        = htons(4000);
  a_sockaddr.sin_addr.s_addr = INADDR_ANY;
  // Adresse mit Socket binden
  if (bind(sock, (struct sockaddr*) &a_sockaddr, sizeof(struct sockaddr_in)) == -1) {
    perror("(bind) ");
    return;
  }
  // Neue Verbindungen annehmen
  if(listen(sock, SOMAXCONN) == -1) {
    perror("(listen) ");
    return;
  }


Dann sollte es klappen, den Port anschliessend wieder erneut zu belegen. Die Zauberfunktion heisst: setsockopt mit dem Wert SO_REUSEADDR
entelechie
Mitglied

Benutzerprofil
Anmeldungsdatum: 04.05.2002
Beiträge: 647
Beitrag entelechie Mitglied 17:13:53 28.10.2004   Titel:              Zitieren

der port (bzw. der socket) wird vom kernel offen gehalten um noch evtl
eintreffende pakete der gegenseite zu verarbeiten
(das verhindert z.b. das du einen neuen socket anlegst und "alte"
pakete erhaelst die an den socket gerichtet sind).

du kannst den socket in einem solchen fall dennoch direkt
verwenden ueber SO_REUSEADDR und SO_REUSEPORT.

C/C++ Code:
int on =1;
setsockopt(socket,SOL_SOCKET,SO_REUSEPORT,&on,sizeof(on));
C/C++ Code:
int on =1;
setsockopt(socket,SOL_SOCKET,SO_REUSEPORT,&on,sizeof(on));
C/C++ Code:
int on =1;
setsockopt(socket,SOL_SOCKET,SO_REUSEPORT,&on,sizeof(on));


edit: hm. gleichzeitig nen beitrag mit selben inhalt.
naja fast. bei REUSEPORT musst du als level SOL_SOCKET nehmen :)

_________________
http://cchoernchen.de


Zuletzt bearbeitet von entelechie am 17:16:40 28.10.2004, insgesamt 1-mal bearbeitet
hackbert
Mitglied

Benutzerprofil
Anmeldungsdatum: 03.11.2001
Beiträge: 723
Beitrag hackbert Mitglied 22:11:58 28.10.2004   Titel:              Zitieren

SO_REUSEPORT kennt er bei mir nicht... Ist da 'ne spezielle Header außer <sys/socket.h> und <sys/types.h> nötig?

_________________
http://www.programmierforen.de | KernelWiki
Ringding
Mitglied

Benutzerprofil
Anmeldungsdatum: 05.05.2004
Beiträge: 1335
Beitrag Ringding Mitglied 07:56:14 29.10.2004   Titel:              Zitieren

Von REUSEPORT hab ich auch noch nix gehört. Aber SO_REUSEADDR allein reicht, damit ist das Problem behoben.
hackbert
Mitglied

Benutzerprofil
Anmeldungsdatum: 03.11.2001
Beiträge: 723
Beitrag hackbert Mitglied 18:55:24 29.10.2004   Titel:              Zitieren

Ich bekomme immernoch den selben Fehler, auch wenn ich SO_REUSEADDR benutze... Der Fehler tritt bei bind() auf.

_________________
http://www.programmierforen.de | KernelWiki
wischmop2
Mitglied

Benutzerprofil
Anmeldungsdatum: 04.05.2001
Beiträge: 127
Beitrag wischmop2 Mitglied 11:46:28 30.10.2004   Titel:              Zitieren

Was tritt bei Dir denn für ein Fehler auf?
Du schreibst, dass der Compiler bei Dir (auch) "SO_REUSEADDR" nicht kennt und der Fehler bei "bind" auftritt? Aber bei "bind" kommt "SO_REUSEADDR" doch gar nicht vor, sondern bei "setsockopt"!
Hast Du nun ein Compilerproblem oder ein Laufzeitproblem?
hackbert
Mitglied

Benutzerprofil
Anmeldungsdatum: 03.11.2001
Beiträge: 723
Beitrag hackbert Mitglied 12:04:22 30.10.2004   Titel:              Zitieren

Das musst Du falsch verstanden haben, oder ich habe mich missverständlich ausgedrückt... SO_REUSEADDR bei setsockopt funktioniert. Kompilieren ist überhaupt garkein Problem. Ich habe ein Laufzeitproblem. Wenn das Programm einmal gestartet wurde und abgestürzt ist, dann ist der Port für eine gewisse Zeit immernoch besetzt, dass heißt die neue Instanz des Programms kann bind() nicht richtig ausführen.

_________________
http://www.programmierforen.de | KernelWiki
wischmop2
Mitglied

Benutzerprofil
Anmeldungsdatum: 04.05.2001
Beiträge: 127
Beitrag wischmop2 Mitglied 13:04:58 30.10.2004   Titel:              Zitieren

Komisch ?!?
Also wenn Du den Sourcecode oben, so wie ich das Beispiel geschrieben habe nimmst und übersetzt (oben noch um includes erweitern und unten um eine sinnvolle Accept-Loop), dann kann ich das Programm mit Strg+C oder auch mit "kill -9 <pid>" abschiessen und sofort wieder funktionsfähig startet. Ich würde darauf tippen, das der Fehler dann noch woanders liegen muss.
Ich hatte auch mal das Problem, daß ein Programm von mir abgestürzt ist und dann Dein Problem zeigte, aber mit der obigen Änderung ging es dann - probier's mal an einer kleinen Testanwendung aus. In meinem Fall habe ich aber auch mit Threads gearbeitet, verwendest Du vielleicht Prozesse (d.h. fork) in der Accept-Loop? Vielleicht laufen dann noch Zombi-Prozesse?
entelechie
Mitglied

Benutzerprofil
Anmeldungsdatum: 04.05.2002
Beiträge: 647
Beitrag entelechie Mitglied 13:09:03 30.10.2004   Titel:              Zitieren

wischmop2 schrieb:
Komisch ?!?
Also wenn Du den Sourcecode oben, so wie ich das Beispiel geschrieben habe nimmst und übersetzt (oben noch um includes erweitern und unten um eine sinnvolle Accept-Loop), dann kann ich das Programm mit Strg+C oder auch mit "kill -9 <pid>" abschiessen und sofort wieder funktionsfähig startet. Ich würde darauf tippen, das der Fehler dann noch woanders liegen muss.


wie lange der port nach dem programmende noch im listen zustand bleibt
hangt vom jeweiligen system ab. es ist durchaus moeglich, dass dein
system ein sofortiges wiederbelegen des ports erlaubt, ein
anderes aber erst nach einer bestimmten zeitspanne.

SO_REUSEPORT scheinen wohl nicht alle systeme zu unterstuetzen.

_________________
http://cchoernchen.de
C/C++ Forum :: FAQ - Linux/Unix ::  Port auch nach Absturz besetzt  
Gehen Sie zu Seite 1, 2  Weiter
Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können keine Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum nicht antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.de ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info, www.c-sar.de, www.c-plusplus.net und www.baeckmann.de enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.