Nowe posty

Autor Wątek: program pobierający dane o serwerze (nazwa)  (Przeczytany 8500 razy)

  • Gość
program pobierający dane o serwerze (nazwa)
« dnia: 2010-02-11, 19:15:54 »
Napisałem program taki: (poniżej). Nie wiem czemu wysypuje się przez segmentation fault. Szukałem błędu, ale nie znalazłem. Ktoś mógłby pomóc?

Kod: c [Zaznacz]
#include 
#include
#include
#include
#include
#include

int main (int argc, char *argv[], char *env[]){
int gniazdo = 0;
char bufor[4096];
char* pozycja;
char* pozycja2;
struct sockaddr_in host;
struct hostent *host_dane;
int wynik;
char *zapytanie;
char koniec[] = "\\r\\n\\r\\n";
if (argc==1) {
printf ("Nie podałeś żadnego hosta");
return 1;
}

zapytanie = (char *)malloc (4096);
gniazdo = socket (PF_INET, SOCK_STREAM, 0);

if (gniazdo==-1) {
printf ("Nie powiodło się tworzenie gniazda");
}

host_dane = gethostbyname (argv[1]);
if (host_dane==NULL){
printf ("Błąd przy tłumaczeniu domeny");
return 1;
}

zapytanie = "GET / HTTP/1.1\\r\\nHost: ";
strcat (zapytanie, host_dane->h_name);
strcat (zapytanie, koniec);

bzero (&host, sizeof(host));

host.sin_family = PF_INET;
host.sin_port = htons (80);
host.sin_addr  = *(struct in_addr*)host_dane->h_addr;

wynik = connect (gniazdo, (struct sockaddr*)&host, sizeof(host));
if (wynik==-1){
printf ("Nie udało mnie się połączyć");
perror("szkoda:");
return 1;
}

wynik = 1;

send (gniazdo, zapytanie, sizeof(zapytanie), 0);
do {

wynik = recv (gniazdo, bufor, sizeof(bufor), 0);

pozycja = strstr (bufor, "Server: ");
if (pozycja!=NULL){
pozycja2 = strstr (pozycja, "\\r\\n");
if (pozycja2!=NULL) *pozycja = '\\0';
printf ("%s", pozycja);
break;
}

} while (wynik>0);
free (zapytanie);
close (gniazdo);

return 0;
}


--edit ZipoKing--
Dodanie BBCode (w tym poście i poniżej)

chmooreck

  • Gość
program pobierający dane o serwerze (nazwa)
« Odpowiedź #1 dnia: 2010-02-11, 21:33:54 »
zatrudnij gdb

nie reagujesz na błąd utworzenia socketa (oprócz wypisania komunikatu)

segfault jest spowodowany najprawdopodobniej próbą zwolnienia wskaźnika do statycznego obszaru pamięci
free(zapytanie)
Więcej nie podpowiem ;-)

Edit:
Polecam użycie snprintf().
Edit2:
te strcat()'y w Twoim wydaniu też nie są najlepszym pomysłem...
Edit3:
Czytaj warningi ;-)

  • Gość
program pobierający dane o serwerze (nazwa)
« Odpowiedź #2 dnia: 2010-02-11, 22:08:48 »
Hmm... gdb to był dobry pomysł. Sypie się jednak na strncat:

(gdb) print host_dane.h_name
$2 = 0x804c14f "www.l.google.com"
(gdb) print host_dane.h_adr_list
There is no member named h_adr_list.
(gdb) print host_dane.h_adr_list[0]
There is no member named h_adr_list.
(gdb) next
38 strncat (zapytanie, host_dane->h_name, 4096);
(gdb) print zapytanie
$3 = 0x8048b18 "GET / HTTP/1.1\\r\\nHost: "
(gdb) print host_dane->h_name
$4 = 0x804c14f "www.l.google.com"
(gdb) step
strncat (s1=0x8048b18 "GET / HTTP/1.1\\r\\nHost: ",
    s2=0x804c14f "www.l.google.com", n=4096) at strncat.c:40
40 strncat.c: No such file or directory.
in strncat.c
(gdb)
41 in strncat.c
(gdb)
41 in strncat.c
(gdb)
41 in strncat.c
(gdb)
41 in strncat.c
(gdb)
41 in strncat.c
(gdb)
41 in strncat.c
(gdb)
41 in strncat.c
(gdb)
41 in strncat.c
(gdb)
41 in strncat.c
(gdb)
41 in strncat.c
(gdb)
41 in strncat.c
(gdb)
41 in strncat.c
(gdb)
41 in strncat.c
(gdb)
41 in strncat.c
(gdb) stepi
0x00d250b8 41 in strncat.c
(gdb)
0x00d250b0 40 in strncat.c
(gdb)
0x00d250b3 40 in strncat.c
(gdb)
41 in strncat.c
(gdb)
0x00d250b8 41 in strncat.c
(gdb)
0x00d250b0 40 in strncat.c
(gdb)
0x00d250b3 40 in strncat.c
(gdb)
41 in strncat.c
(gdb)
0x00d250b8 41 in strncat.c
(gdb)
0x00d250b0 40 in strncat.c
(gdb)
0x00d250b3 40 in strncat.c
(gdb)
41 in strncat.c
(gdb)
0x00d250b8 41 in strncat.c
(gdb)
0x00d250b0 40 in strncat.c
(gdb)
0x00d250b3 40 in strncat.c
(gdb)
41 in strncat.c
(gdb)
0x00d250b8 41 in strncat.c
(gdb)
0x00d250b0 40 in strncat.c
(gdb)
0x00d250b3 40 in strncat.c
(gdb)
41 in strncat.c
(gdb)
0x00d250b8 41 in strncat.c
(gdb)
0x00d250b0 40 in strncat.c
(gdb)
0x00d250b3 40 in strncat.c
(gdb)
41 in strncat.c
(gdb)
0x00d250b8 41 in strncat.c
(gdb)
0x00d250b0 40 in strncat.c
(gdb)
0x00d250b3 40 in strncat.c
(gdb)
41 in strncat.c
(gdb)
0x00d250b8 41 in strncat.c
(gdb)
0x00d250b0 40 in strncat.c
(gdb)
0x00d250b3 40 in strncat.c
(gdb)
41 in strncat.c
(gdb)
0x00d250b8 41 in strncat.c
(gdb)
0x00d250b0 40 in strncat.c
(gdb)
0x00d250b3 40 in strncat.c
(gdb)
41 in strncat.c
(gdb)
0x00d250b8 41 in strncat.c
(gdb)
45 in strncat.c
(gdb)
47 in strncat.c
(gdb)
0x00d250c0 47 in strncat.c
(gdb)
49 in strncat.c
(gdb)
0x00d250c4 49 in strncat.c
(gdb)
52 in strncat.c
(gdb)
54 in strncat.c
(gdb)
53 in strncat.c
(gdb)

Program received signal SIGSEGV, Segmentation fault.
strncat (s1=0x8048b2d " ", s2=0x804c14f "www.l.google.com", n=4096)
    at strncat.c:53
53 in strncat.c
(gdb)

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
(gdb)
Tylko zastanawiam się czemu, z resztą wywoływałem argument pierwszy strncat z zawartością a przy wysypaniu się nie wiadomo czemu opróżnił

jk33

  • Gość
program pobierający dane o serwerze (nazwa)
« Odpowiedź #3 dnia: 2010-02-11, 22:36:31 »
Cytat: Xgrzyb90
Hmm... gdb to był dobry pomysł. Sypie się jednak na strncat:

Tylko zastanawiam się czemu, z resztą wywoływałem argument pierwszy strncat z zawartością a przy wysypaniu się nie wiadomo czemu opróżnił
1) Ale powód błędu jest nadal ten sam. (do jakiej pamięci chcesz dopisać string)?

2) Wynika to ze specyfiki działania funkcji srt(n)cat i nie jest błędem.  (możesz się dowiedzieć jak działa ta funkcja).

chmooreck

  • Gość
program pobierający dane o serwerze (nazwa)
« Odpowiedź #4 dnia: 2010-02-11, 22:41:37 »
Co Twoim zdaniem robi:
zapytanie = "GET / HTTP/1.1\\r\\nHost: ";
?

  • Gość
program pobierający dane o serwerze (nazwa)
« Odpowiedź #5 dnia: 2010-02-11, 23:04:42 »
Hmm... za bardzo przyzwyczaiłem się do beztroski i tolerancji php. Pojawia się też kolejny problem... Program zamraża się przy funkcji recv (nie crashuje ale stoi w miejscu), jakby non stop odbierał, ale de facto pętla (odbioru danych) ani razu się nie wykonuje.

47   wynik = connect (gniazdo, (struct sockaddr*)&host, sizeof(host));
(gdb)
48   if (wynik==-1){
(gdb)
53   wynik = 1;
(gdb)
55   wynik = send (gniazdo, zapytanie, sizeof(zapytanie), 0);
(gdb)
57   if (wynik==-1){
(gdb) print wynik
$1 = 4
(gdb) step
64   wynik = recv (gniazdo, bufor, sizeof(bufor), 0);
(gdb) print zapytanie
$2 = 0x804b008 "GET / HTTP/1.1\\r\\nHost: www.l.google.com\\r\\n\\r\\n"
(gdb) print wynik
$3 = 4
(gdb) next

chmooreck

  • Gość
program pobierający dane o serwerze (nazwa)
« Odpowiedź #6 dnia: 2010-02-12, 08:10:37 »
czeka aż się uzbiera 4096 bajtów danych.. być może serwer aż tyle nie wysyła...

  • Gość
program pobierający dane o serwerze (nazwa)
« Odpowiedź #7 dnia: 2010-02-12, 11:49:13 »
Nie w tym tkwił błąd, gdzieś indziej musiałem to spaprać. Ograniczyłem bufor najpierw do 256, potem do 1 i tak nie działało.

Napisałem więc od nowa program.

Mam pytanie odnośnie działania programu. Program ten który już napisałem (nawet działa), ma za zadanie wyszukać pierwsze wystąpienie nagłówka Server i wyświetlić zawartość. Mój program wyszukuje jego wystąpienie w buforze 'bufor'. Ale czy może zdarzyć się że jedna część nagłówka Server np. '\\r\\nServ' Będzie odebrane za jednym razem, a kolejna część w następnym razie, a de facto program nie znajdzie tego wystąpienia (błędnie)?. Chciałbym też się zapytać dlaczego jak ograniczę bufor do np. 10 bajtów to występuje segmentation fault?

chmooreck

  • Gość
program pobierający dane o serwerze (nazwa)
« Odpowiedź #8 dnia: 2010-02-12, 16:37:50 »
Cytat: Xgrzyb90
Mam pytanie odnośnie działania programu. Program ten który już napisałem (nawet działa), ma za zadanie wyszukać pierwsze wystąpienie nagłówka Server i wyświetlić zawartość. Mój program wyszukuje jego wystąpienie w buforze 'bufor'. Ale czy może zdarzyć się że jedna część nagłówka Server np. '\\r\\nServ' Będzie odebrane za jednym razem, a kolejna część w następnym razie, a de facto program nie znajdzie tego wystąpienia (błędnie)?.
Może.

Cytat: Xgrzyb90
Chciałbym też się zapytać dlaczego jak ograniczę bufor do np. 10 bajtów to występuje segmentation fault?
Wróżką nie jestem.

jk33

  • Gość
program pobierający dane o serwerze (nazwa)
« Odpowiedź #9 dnia: 2010-02-12, 17:04:30 »
Cytat: chmooreck
Cytat: Xgrzyb90
Chciałbym też się zapytać dlaczego jak ograniczę bufor do np. 10 bajtów to występuje segmentation fault?
Wróżką nie jestem.
Ja bym strzelał, że ponieważ wtedy nie występuje w buforze ciąg Server:, to wywala się strstr. ;)
(co pewnie potwierdzi debuger).

chmooreck

  • Gość
program pobierający dane o serwerze (nazwa)
« Odpowiedź #10 dnia: 2010-02-12, 23:03:17 »
Bufor przekazany do strstr() nie jest zakończony zerem i jedziemy w nieznane ;-)
...ale ponoć program został napisany od nowa, więc gdybać sobie możemy.

Ksanderon

  • Gość
program pobierający dane o serwerze (nazwa)
« Odpowiedź #11 dnia: 2010-03-17, 12:23:02 »
co do stania recv- to zupełnie normalne- moim zdaniem najlepiej przed recv zrobić hmm... jeśli zależy ci na wydajności to fork() i czekać z 1/200 sekundy a jak nie to tylko czekać. dobrze zrobić też przedtem coś takiego jak gniazda "nie blokujące" i odbierać w while. w takim gnieździe recv() na nic nie czeka, zwraca n>0 gdy coś przyszło i nie jest to koniec transmisji, n=0(tylko raz!) gdy transmisja zostanie przerwana lub n<0 gdy coś jest nie tak - np. w serwerach gdy wywołasz zaraz po accept. ogólnie jeśli chodzi o programowanie sieci to polecam: "beej network guide" -> jak pogooglujesz to nawet po polsku znajdziesz.

Ksanderon

  • Gość
program pobierający dane o serwerze (nazwa)
« Odpowiedź #12 dnia: 2010-03-17, 12:25:49 »
segmentation fault to błąd związany z pamięcią np. nadpisywanie nie swojego obszaru.