Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.
snail.c - Programm hängt
Hallo,
wenn ich versuche, mein Programm mit dem auf dem Blatt angegebenen Server zu verbinden, hängt sich mein Programm auf.
Folgendes Programm terminiert bei mir nicht, wobei der Übersicht wegen sämtliche Fehlerfälle ignoriert wurden ;):
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
int main(int argc, char *argv[]) {
struct addrinfo hints = {
.ai_socktype = SOCK_STREAM,
.ai_family = PF_UNSPEC,
.ai_flags = AI_ADDRCONFIG,
};
struct addrinfo *head;
getaddrinfo("faui06c.cs.fau.de","25",&hints, &head);
printf("A");
int sock;
struct addrinfo *curr;
for (curr = head; curr != NULL; curr = curr->ai_next) {
sock = socket(curr->ai_family, curr->ai_socktype, curr->ai_protocol);
if(sock == -1)
continue;
if(connect(sock, curr->ai_addr, curr->ai_addrlen) != -1)
break;
}
}
“A” wird dabei nicht ausgegeben.
Wo könnte mein Fehler liegen?
Vielen Dank!
dann wohl irgendwo bei getaddrinfo, check mal durch ob alle übergebenen werte passen. (habs grad nich im kopf und zu faul nachzuschauen :D)
edit: müsste doch stimmen, liegt dann wohl am server? versuch mal einen anderen, hatte in meiner alten abgabe zB. faui03.cs.fau.de
stdout ist gepuffert, d.h. nicht alle Ausgaben, die du mit printf tätigst, erscheinen direkt in deinem Terminal. Du kannst das umgehen, indem du nach dem printf() ein fflush(stdout); einfügst, um die Ausgabe zu erzwingen. Alternativ ist es für so etwas sinnvoll, stderr zu verwenden (fprintf(stderr, …);). In diesem Code ist die fehlende Ausgabe kein Garant dafür, dass das printf wirklich nicht ausgeführt wurde.
Terminiert dein Programm wirklich nie oder braucht es nur sehr, sehr lange? Etwas, das endlos blockiert, sehe ich auf Anhieb nicht. Allerdings solltest du nicht auf die faui06c verbinden, sondern auf die faui03 - auf der faui06c läuft kein Mailserver, der deine Mail annehmen wird.
Als Alternative zum [m]fflush(3)[/m] reicht bei einer Ausgabe nach stdout (allerdings nicht bei Sockets oder Dateien) auch ein Newline: [m]printf(“A\n”);[/m]
Denk auch an die Fehlerbehandlung, dann kannst du zusätzliche Probleme ausschließen.
Falscher Server? faui03.cs.fau.de antwortet auf Port 25 entgegen faui06c (und steht so auch auf der Aufgabe)
EDIT: Ich habe nur beim Übertragen des Quellcodes in das Forum versehentlich faui06 statt faui03 eingetragen. Getestet habe ich jedoch mit faui03.
Auch mit dem Server faui03.cs.fau.de ergibt sich ähnliches Verhalten. Das “A” wird nach fflush(3) ausgegeben.
Habe nochmal länger gewartet und das Programm terminiert tatsächlich zweimal genau nach 2 Minuten und 6 Sekunden. Gibt es da irgendeine Timeout-Variable, die ich einstellen kann? (errno zeigt “Connection timed out” an)
Und woran kann das nun liegen, dass sich mein Programm nicht mit dem Server verbinden kann? Wenn ich das Programm auf dem Rechner faui03c ausführe erhalte ich ein “Connection refused”.
if(connect(sock, curr->ai_addr, curr->ai_addrlen) == 0){
fprintf(stderr, "bla\n");
break;
}
kommt das bla?
Ja, das “bla” erscheint.
dann läuft bis hier hin alles richtig denke ich… dein code geht später kaputt
versuchst du was an den server zu senden? hast du am ende von dem zu sendenden string “\r\n” stehen?
Benutzt du [m]FILE *[/m] zur Kommunikation? Kann’s sein, dass du kein [m]fflush()[/m] machst und deswegen die zu sendenden Daten noch im Zwischenpuffer hängen?
Hm, komischerweise funktioniert es jetzt - ohne dass ich am Programm etwas geändert hätte…
Danke für eure Unterstützung
Das ist komisch, ich habe genau das gleiche Problem.
Mein Code ist nahezu identisch (siehe auch Übungsfolie 1-23).
Nach dem Durchlaufen der addrinfo-Liste habe ich noch
if (curr == NULL) {
// Keine brauchbare Adresse gefunden
printf("foo");
}
Es sieht so aus, als würde das Programm ein Weilchen am connect hängen, jedoch keine Verbindung zustande bekommen und als letztes und einziges Listenelement aus der Schleife springen. Daraufhin wird [m]foo [/m]ausgegeben. Kann das vielleicht auch am Server liegen?
Edit: Anscheinend habe ich das Problem nur von zuhause aus. Führe ich das Programm im Cip aus, scheint es tadellos zu funktionieren.
Bei mir funktionierts mit dem Server ohne Probleme. Ich nehme an du probierst das auch aus dem CIP heraus aus? Von extern klappt das nämlich nicht (und führt bei mir aktuell auch zu einem „Hängen“).
EDIT: Ja, der Server spielt kein Relay für externe, unbekannte Nutzer.
gibt es eine MAX_LENGTH für pw_gecos
? Habe in der betreffenden manpage und mit google nichts gefunden. Würde getUserName nämlich gerne aus meiner main haben, aber dafür muss ich vorher wissen, wie groß das maximal wird
nope.
einfach dynmisch zuweisen.
Hint Edit: nicht immer nur in Arrays denken.
Mein Problem ist, dass ich das [m]passwdstruct->pw_gecos[/m] noch mit [m]strtok[/m] bearbeiten muss und wenn ich dann [m]char *tmp = strtok(…); return tmp;[/m] innerhalb meiner Funktion mache geht das kaputt, weil ich den Pointer auf dem Stack der Funktion liegen hab
[m]
pw_gecos[/m] alleine könnte ich vermutlich returnen…
und als Lösung für dieses Problem dachte ich mir: erstell dir einfach nen Pointer, den du beim Aufruf dann übergibst… leider funktioniert das nicht, wenn ich die Größe von dem Ding nicht vorher kenne
Dann hol dir die Informationen doch einfach in der Funktion, in der du sie auch brauchst.
Richtig. Zugriffe auf Port 25 von außerhalb des Uninetzwerks werden durch das RRZE weggefiltert.
Mein Problem ist, dass ich das [m]passwdstruct->pw_gecos[/m] noch mit [m]strtok[/m] bearbeiten muss und wenn ich dann [m]char *tmp = strtok(…); return tmp;[/m] innerhalb meiner Funktion mache geht das kaputt, weil ich den Pointer auf dem Stack der Funktion liegen hab
Also eigentlich sollte das funktionieren, denn der Pointer zeigt irgendwo in einen statischen Bereich der von der libc bereit bestellt wird. Wo der Pointer selbst liegt ist egal, denn bei der Rückgabe wird der Pointer an sich kopiert, der Speicherbereich auf den der zeigt natürlich nicht. Schön ist das aber nicht.
Prinzipiell kannst du dir natürlich mit [m]strlen(3)[/m] die Länge des Strings holen und dann passend mit [m]malloc(3)[/m] Speicher anfordern.
Aber die ganze Aufgabe geht wunderbar ohne ein einziges [m]malloc(3)[/m]. Man sollte nicht alles in Funktionen auslagern, sondern nur dann wenn es sinnvoll ist. Bei dieser Aufgabe sollte man vieles direkt in der [m]main()[/m] machen.
und als Lösung für dieses Problem dachte ich mir: erstell dir einfach nen Pointer, den du beim Aufruf dann übergibst… leider funktioniert das nicht, wenn ich die Größe von dem Ding nicht vorher kenne
Ich hoffe du meinst, du erstellst einen Buffer auf dem Stack und übergibst den Pointer darauf.