Seite 1 von 1

HTTP-Request liefert keine Antwort

Verfasst: Mi Dez 02, 2020 6:32 pm
von Lolek
Hallo Leuts,

ich versucht gerade autodidaktisch c zu lernen. Ich habe schon einige Versuche gemacht, habe aber jetzt ein Problem mit dem ich nicht weiter komme.

Das Ziel ist es eine Textdatei über http zu lesen und den darin gespeicherten Text auszuwerten. Es ist mir bewusst, dass es für einen Anfänger etwas vermessen ist sich an Sockets zu versuchen. :shock: Der Socket ist aber ein notwendiges Übel um an die Datei zu kommen. Ich habe mir aus dem Netz ein Code- Beispiel geladen und es angepasst.

Ich kann den Code unter Linux compilieren und auch ausführen. Mit folgendem Aufruf kann ich eine CSS Datei von meiner Fritzbox laden und im Terminal ausgeben.

Code: Alles auswählen

prog fritz.box /css/rd/login.css
Die Textdatei die ich laden will befindet sich auf einem Raspi mit openwrt und dem Webserver uhttpd.
Ich habe versucht die Textdatei mit folgendem Aufruf zu lesen.

Code: Alles auswählen

prog raspi.im.lan /bla/bla.txt
Nach dem Aufruf bleibt der Terminal schwarz und das Programm wird nach einer gewissen Zeit ohne Fehler beendet.

Könnte mir jemand bei dem Problem weiter helfen? Vorab schon mal danke für alle Antworten.

Hier ist der Code.

Code: Alles auswählen

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
/* Windows-System */
#ifdef _WIN32
#include <winsock.h>
#include <io.h>
/* Unix-System */
#else
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#endif
#define HTTP_PORT 80

int main(int argc, char **argv){
	int sock;
	struct sockaddr_in host_addr;
	struct hostent *hostinfo;
	char *host, *file;
	char command[1024];
	char buf[1024];
	unsigned int bytes_sent, bytes_recv;
	/* Ist der Aufruf korrekt? */
	if (argc != 3) {
		fprintf (stderr, "Aufruf: httprecv host file\n");
		exit (EXIT_FAILURE);
	}
	host = argv[1];
	file  = argv[2];
	/* ggf. Winsock initialisieren */
	#ifdef _WIN32W
	SADATA wsaData;
	if (WSAStartup (MAKEWORD(1, 1), &wsaData) != 0) {
		fprintf (stderr, "WSAStartup(): Kann Winsock nicht initialisieren.\n");
		exit (EXIT_FAILURE);
	}
	#endif
	/* Socket erzeugen */
	sock = socket (AF_INET, SOCK_STREAM, 0);
	if (sock == -1) {
		perror ("socket()");
		exit (EXIT_FAILURE);
	}
	/* Adresse des Servers festlegen */
	memset( &host_addr, 0, sizeof (host_addr));
	host_addr.sin_family = AF_INET;
	host_addr.sin_port = htons (HTTP_PORT);
	host_addr.sin_addr.s_addr = inet_addr (host);
	if (host_addr.sin_addr.s_addr == INADDR_NONE) {
		/* Server wurde nicht mit IP sondern mit dem Namen angegeben */
		hostinfo = gethostbyname (host);
		if (hostinfo == NULL) {
			perror ("gethostbyname()");
			exit (EXIT_FAILURE);
		}
		memcpy((char*) &host_addr.sin_addr.s_addr, hostinfo->h_addr, hostinfo->h_length);
	}
	/* Verbindung aufbauen */
	if (connect(sock, (struct sockaddr *) &host_addr, sizeof(struct sockaddr)) == -1) {
		perror ("connect()");
		exit (EXIT_FAILURE);
	}
	/* HTTP-GET-Befehl erzeugen */
	sprintf (command, "GET %s HTTP/1.0\nHost: %s\n\n", file, host);
	/* Befehl senden */
	bytes_sent = send (sock, command, strlen (command), 0);
	if (bytes_sent == -1) {
		perror ("send()");
		exit (EXIT_FAILURE);
	}
	// Antwort des Servers empfangen und ausgeben */
	while ((bytes_recv = recv (sock, buf, sizeof(buf), 0)) > 0) {
		write (1, buf, bytes_recv);
	}
	if (bytes_recv == -1) {
		perror ("recv()");
		exit (EXIT_FAILURE);
	}printf ("\n");
	#ifdef _WIN32
	closesocket(sock);
	WSACleanup();
	#else
	close(sock);
	#endif
	return 0;
}

EDIT nufan: Titel (war "Anfängerproblem")

Re: Anfängerproblem

Verfasst: Mi Dez 02, 2020 6:38 pm
von Xin
Bevor ich mir das Programm genauer angucke... auf welchem System compilierst und testest Du denn überhaupt?

Und wo kommt das Programm her?

Re: Anfängerproblem

Verfasst: Mi Dez 02, 2020 7:03 pm
von nufan
Der HTTP-Standard (https://tools.ietf.org/html/rfc2616) erwartet sich "\r\n" zwischen den Zeilen, nicht bloß "\n". Möglicherweise ist uhttpd in diesem Fall strenger als die Fritzbox und erkennt deinen Request nicht?

Ansonsten würde ich empfehlen im Hintergrund den Netzwerkverkehr mit z.B. Wireshark mitzuschneiden und am Server einen Blick in die Access-Logs zu werfen.

Re: Anfängerproblem

Verfasst: Mi Dez 02, 2020 7:56 pm
von Lolek
Ups, das ging ja schnell. Super!

Vielen Dank für die Antworten.

@Xin: Ich hatte oben im Text geschrieben, dass ich das Programm unter Linux compiliert habe. Ich habe es mit gcc im Terminal übersetzt (gcc prog.c -o prog). Den Code habe ich aus einem Tutorial über Socket Programmierung. Das was ich hier abgebildet habe ist der original Code, den ich mit der Fritzbox, wie oben beschrieben, getestet habe. Ich habe mit dem Code in einem Testprogramm etwas rumgespielt, um einigermassen zu verstehen was eigentlich abläuft. Ist aber noch ziemlich kryptisch für mich. :roll:

@ nufan: Danke für den Tipp mit dem RFC. Ich werde das gleich testen.

Re: Anfängerproblem

Verfasst: Mi Dez 02, 2020 8:17 pm
von Lolek
Hurra!
so hat es funktioniert.

Code: Alles auswählen

sprintf (command, "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n", file, host);
Vielen Dank für die Unterstützung und schöne Weihnachten.

Re: Anfängerproblem

Verfasst: Mi Dez 02, 2020 8:35 pm
von Xin
Lolek hat geschrieben:
Mi Dez 02, 2020 7:56 pm
@Xin: Ich hatte oben im Text geschrieben, dass ich das Programm unter Linux compiliert habe.
Okay... das habe ich überlesen.

Schön, dass es jetzt funktioniert. :-)

Re: Anfängerproblem

Verfasst: Mi Dez 02, 2020 8:42 pm
von Lolek
Jo, danke nochmal.