Dateiübertragung über Socket funktioniert nicht richtig?

Schnelle objektorientierte, kompilierende Programmiersprache.
Proxic
Beiträge: 14
Registriert: So Apr 24, 2016 9:38 pm

Dateiübertragung über Socket funktioniert nicht richtig?

Beitrag von Proxic » Mo Apr 25, 2016 1:33 am

Ich versuche nun schon seit einigen Tagen Bilder und andere Dateien als nur text und html Dateien über ein Socket an den Client zu schicken aber leider komme ich gerade einfach nicht weiter. Ich habe eine Funktion geschrieben um die Dateien erst einmal in einen Buffer zu lesen und anschließend mit write an den Client zu schicken aber das funktioniert derzeit, wie oben schon geschrieben nur mit html- und Textdateien, wie es scheint.

Code: Alles auswählen

int send_resource(int nsockfd, int fd) {
    char buf[FILE_BUF] = {0};

    int bytes_to_write = read(fd, buf, sizeof(buf));
    if(bytes_to_write < 0) {
    	exit(1);
    }

    void *ptr = buf;
    while(bytes_to_write > 0) {
    	int bytes_written = write(sockfd, ptr, bytes_to_write);
    	if(bytes_written <= 0) {
    		exit(1);
    	}

    	bytes_to_write -= bytes_written;
    	ptr += bytes_written;
    }
    return 1;
}
Ich habe auch schon eine Funktion um den mime Typen zu bestimmen und in dem Content Type dementsprechend einzutragen und außerdem berechne ich auch die Content Length aber leider kriege ich es einfach nicht hin, dass die Bilder angezeigt werden und das die Javascript Datei auch funktioniert. So sieht bspw. eine Response von meinem Webserver aus. Ich habe dafür die Software "Burp Suite" verwendet, damit ich mir die Response anschauen kann.

Code: Alles auswählen

HTTP/1.1 200 OK
Server: Custom Webserver
Content-Type: text/html
Content-Length: 438

<html>
  <head>
    <title>Test file</title>
    <script language="JavaScript" src="js/javascript.js" ></script>
  </head>
  <body>
    <p> A simple test file ...
      <br/>
      <a href="javascript:testf();">Click</a>
      <script>testf();</script>
    </p>
  </body>
</html>

Code: Alles auswählen

HTTP/1.1 200 OK
Server: Custom Webserver
Content-Type: text/javascript
Content-Length: 74

function testf() {
    alert("The js file has been loaded");
}
Die Bilder lasse ich hier jetzt lieber mal aus, weil das einfach zu viel für den Beitrag wäre und mit Sicherheit den Rahmen sprengen würde. In der Response steht dann aber auch der richtige Content Type usw. aber die Bilder werden nicht dargestellt und die JS Datei funktioniert auch nicht, also wenn die Seite geladen wurde passiert nichts und wenn ich auf den Text klicke passiert nichts.

Das Öffnen der Dateien und finden der Dateien und vieles anderes funktioniert schon, von dem was ich mir bei der Programmierung eines eigenen Webservers vorgestellt habe aber das mit den Dateien, wie jpeg, png, js usw. leider nicht, obwohl er die Dateien doch anscheinend an den Client, also mich schickt? Was mache ich also falsch?
Ich komme nicht weiter ...

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Dateiübertragung über Socket funktioniert nicht richtig?

Beitrag von Xin » Mo Apr 25, 2016 11:06 am

Ich habe einen funktionsfähigen Webserver in C++ geschrieben, da bekommen wir Deinen wohl auch ans Laufen ;)

BurpSuite kenne ich nicht... daher weiß ich jetzt auch nicht, wo Du die Response her hast.

Funktioniert das - und wenn ja-wie?

Code: Alles auswählen

    void *ptr = buf;
    while(bytes_to_write > 0) {
       int bytes_written = write(sockfd, ptr, bytes_to_write);
       if(bytes_written <= 0) {
          exit(1);
       }

       bytes_to_write -= bytes_written;
       ptr += bytes_written;
    }
Warum void* ptr? Wie groß ist ein void? Was passiert, wenn Du bytes_written voids weitergehst?
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Proxic
Beiträge: 14
Registriert: So Apr 24, 2016 9:38 pm

Re: Dateiübertragung über Socket funktioniert nicht richtig?

Beitrag von Proxic » Mo Apr 25, 2016 5:32 pm

Das hört sich ja gut an. Ich hatte schon ein wenig Angst, weil mir hier vielleicht niemand helfen kann oder ähnliches aber da scheine ich ja dann doch Glück gehabt zu haben. Vielleicht bist du ja auch nicht der einzige hier aber das weiß ich nicht.

Burp ist ein Programm was als Proxy fungiert und dadurch laufen die Anfragen dann ja über das Programm und man kann diese dann auch manipulieren, einsehen und was halt sonst noch so dazu gehört, wie z.B ein Intercept oder ähnliches aber das soltle ja auch nicht so wichtig sein?

Derzeit funktioniert mein Programm wie bereits gesagt soweit, als das ich html- und Textdateien und natürlich einen gültigen Header als Response zurückliefere aber ebend Bild- und Javascriptdateien bspw. nicht. Jetzt wo du das aber mit dem Pointer aufzeigst, frage ich mich auch warum das so bis jetzt funktioniert, weil ich ja auch bspw. keinen Speicherbereich freigebe? Der Typ sollte ja auch eigentlich ein char sein, würde ich mal sagen. Hmm ...

Die Frage wäre doch dann aber auch jetzt, wie viel Speicherbereich ich dann freizugeben habe oder könnte ich mich da nach der strlen (+1) an dem anderen Buffer ausrichten, da diese dann ja gleich groß sein müssten und dann würde das laufen? Ich habe ja erst gedacht dass open mit dem flag 0_RDONLY die Datei vielleicht binär öffnet aber laut den Informationen die ich dazu bis jetzt gefunden habe, soltle das so wie ich es derzeit mit open, read und write habe funktionieren? So dann also?

Code: Alles auswählen

int send_resource(int nsockfd, int fd) {
    char buf[FILE_BUF] = {0};

    int bytes_to_write = read(fd, buf, sizeof(buf));
    if(bytes_to_write < 0) {
       exit(1);
    }

    char *ptr = malloc(strlen(buf) + 1);
    if(ptr == NULL)
    	exit(1);
	
    ptr = buf;
    while(bytes_to_write > 0) {
       int bytes_written = write(sockfd, ptr, bytes_to_write);
       if(bytes_written <= 0) {
          exit(1);
       }

       bytes_to_write -= bytes_written;
       ptr += bytes_written;
    }
    return 1;
}
Ich hoffe mal, dass ich damit richtig liege. Das meintest du doch hoffentlich oder nicht?

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Dateiübertragung über Socket funktioniert nicht richtig?

Beitrag von Xin » Mo Apr 25, 2016 5:59 pm

Muss jetzt gleich erstmal weg... nur ein Gedanke, der mir gerade durch den Kopf schoss:

Code: Alles auswählen

HTTP/1.1 200 OK
Server: Custom Webserver
Content-Type: text/html
Content-Length: 438

<html>
Mach nach Content-Length mal zwei leere Zeilen und achte drauf, dass ein Newline aus "<CR><LF>" besteht.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Proxic
Beiträge: 14
Registriert: So Apr 24, 2016 9:38 pm

Re: Dateiübertragung über Socket funktioniert nicht richtig?

Beitrag von Proxic » Mo Apr 25, 2016 7:10 pm

Meinst du auch mit der oben genannte Änderung an dem Code oder so wie es da oben auch steht? Ich habe es jetzt mal mit der Änderung oben probiert un es funktioniert nicht.
Da sind ja auch schon zwei leere Zeilen? Ich mache zwei mal ein \r\n hinter dem letztem Header, also in dem Fall oben nach dem Content-Length Header. Ich habe es jetzt aber auch noch einmal mit einer zusätzlichen Zeile probiert aber es funktioniert immer noch nicht.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Dateiübertragung über Socket funktioniert nicht richtig?

Beitrag von Xin » Mo Apr 25, 2016 7:54 pm

Proxic hat geschrieben:Meinst du auch mit der oben genannte Änderung an dem Code oder so wie es da oben auch steht? Ich habe es jetzt mal mit der Änderung oben probiert un es funktioniert nicht.
Ich meinte da noch gar nix, das war nur, was mir flott einfiel, weil ich dann weg musste, bevor ich das durchlesen konnte. ^^
Proxic hat geschrieben:Da sind ja auch schon zwei leere Zeilen? Ich mache zwei mal ein \r\n hinter dem letztem Header, also in dem Fall oben nach dem Content-Length Header. Ich habe es jetzt aber auch noch einmal mit einer zusätzlichen Zeile probiert aber es funktioniert immer noch nicht.
Gibt's 'ne Chance, dass man das Ding in Aktion sehen kann? Ich sehe hier ja immer nur einzelne Funktionen und kann den Rest nur raten.
Proxic hat geschrieben:Das hört sich ja gut an. Ich hatte schon ein wenig Angst, weil mir hier vielleicht niemand helfen kann oder ähnliches aber da scheine ich ja dann doch Glück gehabt zu haben. Vielleicht bist du ja auch nicht der einzige hier aber das weiß ich nicht.
Das Forum ist zur Zeit sehr ruhig und ich bin der Hausmeister hier. ;)
Proxic hat geschrieben:Derzeit funktioniert mein Programm wie bereits gesagt soweit, als das ich html- und Textdateien und natürlich einen gültigen Header als Response zurückliefere aber ebend Bild- und Javascriptdateien bspw. nicht. Jetzt wo du das aber mit dem Pointer aufzeigst, frage ich mich auch warum das so bis jetzt funktioniert, weil ich ja auch bspw. keinen Speicherbereich freigebe? Der Typ sollte ja auch eigentlich ein char sein, würde ich mal sagen. Hmm ...
Joah, würde ich auch sagen.
Wozu brauchst Du den ptr überhaupt...?

Code: Alles auswählen

int send_resource(int nsockfd, int fd) {
    char buf[FILE_BUF] = {0};

    int bytes_to_write = read(fd, buf, sizeof(buf));
    if(bytes_to_write < 0) {
       exit(1);
    }
Hier holst Du Dir ein Array der Größe FILE_BUF und lädst eine Datei ein, aber maximal soviel, wie der Buffer groß ist. Ist die Datei größer, fehlt halt ein Stück... das könnte bei Bildern relevant werden...

Code: Alles auswählen

    char *ptr = malloc(strlen(buf) + 1);
    if(ptr == NULL)
    	exit(1);
Hier holst Du Dir Speicher in der Größe der Datei, die Du gerade eingelesen hast - und zwar bis zum ersten Null-Byte. Nullbytes können in Bildern häufiger vorkommen. Ich vermute "bytes_to_write" entspricht eher dem, was Du machen möchtest.
Was Du mit Sicherheit nicht machen willst ist, was Du als nächstes tust.

Code: Alles auswählen

    ptr = buf;
Du hast also Speicher geholt und Dir in ptr gemerkt, wo der Speicher ist. Dann überschreibst Du ptr mit der Adresse von buf.

Code: Alles auswählen

    while(bytes_to_write > 0) {
       int bytes_written = write(sockfd, ptr, bytes_to_write);
       if(bytes_written <= 0) {
          exit(1);
       }

       bytes_to_write -= bytes_written;
       ptr += bytes_written;
    }
    return 1;
}
Und hier gibst Du den Kram an den Socket.
Das sieht auch gut aus.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Proxic
Beiträge: 14
Registriert: So Apr 24, 2016 9:38 pm

Re: Dateiübertragung über Socket funktioniert nicht richtig?

Beitrag von Proxic » Mo Apr 25, 2016 8:52 pm

Das war aber doch wohl berechtigt, würde ich mal so meinen, auch wenn du damit noch so nichts gemeint hast. Jetzt habe ich das ja auch so abgeändert, wie in dem Beitrag etwas weiter oben geschrieben, obwohl es ja auch vorher schon ohne? Probleme funktioniert hat.

Ich würde ungerne den ganzen Code hier posten oder irgendwo hochladen, da das vor allem sehr viel ist und auch weil das meine ganze Arbeit war. Ich hoffe mal, dass das jetzt nicht falsch rüber kommt. Ich würde ihn dir wohl per PN schicken aber müsste man das nicht auch eigentlich so irgendwie lösen können?

Das du der Admin (Hausmeister?) hier bist habe ich schon gesehen aber die Aktivität hier scheint doch ganz okay zu sein. Wenn es hier tot wäre, dann hätte ich mich hier auch nicht angemeldet. Mir gefällt das Aussehen des Forums auch irgendwie sehr und auch das es hier Tutorials gibt, die ich übrigens auch schon gelesen habe. ;)

Den ptr brauche ich um zu bestimmen, wo ich mich gerade befinde, da es ja nicht gesichert ist, dass alles auf einmal geschickt wird, weswegen da ja auch die Schleife drum ist. Das ist ja das zweite Argument der write Funktion. Brauchen tue ich den schon.

Der Buffer ist so definert:

Code: Alles auswählen

#define FILE_BUF 262144
Der sollte ja eigentlich groß genug für alles sein, sogar bestimmt auch für die allermeisten Bilder. Ich berechne ja auch schon die Größe der einzelnen Dateien und die liegen alle bei < 50000. Da wird also auch nichts abgeschnitten. Sehr beunruhigend übrigens das du sagst es sieht alles gut aus. Da habe ich lieber einen Fehler ..

Das einzige was ja höchstens noch von Relevanz ist, dürfte doch das öffnen der Datei sein oder nicht? Das sieht so aus

Code: Alles auswählen

int resource = open(path, O_RDONLY);
und den gebe ich dann an die Funktion send_resource weiter und der Rest davor ist ja nur noch Bestimmung des Pfades, Zugriffsrecht prüfen usw. und die Header scheinen ja auch in Ordnung zu sein. Da sollte ja kein Fehler vorhanden sein.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Dateiübertragung über Socket funktioniert nicht richtig?

Beitrag von Xin » Mo Apr 25, 2016 9:57 pm

Proxic hat geschrieben:Ich würde ungerne den ganzen Code hier posten oder irgendwo hochladen, da das vor allem sehr viel ist und auch weil das meine ganze Arbeit war. Ich hoffe mal, dass das jetzt nicht falsch rüber kommt. Ich würde ihn dir wohl per PN schicken aber müsste man das nicht auch eigentlich so irgendwie lösen können?
Viele Probleme sind Einsteigerkram, das kann man direkt hier ins Forum posten, das sieht man - mit der Erfahrung - auch häufig auf den ersten Blick, aber bei einem Programm mit Client-Server-Architektur, wo überall was schiefgehen kann, so dass am Schluss halt was anderes bzw. nix ankommt. Das ist Raterei.

Ein Webservice und Client habe ich in meinen Tutorien als Übung gemacht. Wenn da also nicht sooo viel drumrum ist - und wie mir scheint, werden die Dateien auch nicht erzeugt, sondern nur kopiert.
Als PM läuft das unter Consulting. Wären 150€ je angefangene Stunde ok? ;)
Proxic hat geschrieben:Das du der Admin (Hausmeister?) hier bist habe ich schon gesehen aber die Aktivität hier scheint doch ganz okay zu sein. Wenn es hier tot wäre, dann hätte ich mich hier auch nicht angemeldet. Mir gefällt das Aussehen des Forums auch irgendwie sehr und auch das es hier Tutorials gibt, die ich übrigens auch schon gelesen habe. ;)
Steckt noch viel Arbeit drin... darfst Dich gerne an einem Artikel über funktionierende Socket-Programmierung beteiligen ;)
Proxic hat geschrieben:Den ptr brauche ich um zu bestimmen, wo ich mich gerade befinde, da es ja nicht gesichert ist, dass alles auf einmal geschickt wird, weswegen da ja auch die Schleife drum ist. Das ist ja das zweite Argument der write Funktion. Brauchen tue ich den schon.
Kein Thema, aber malloc brauchst Du nicht.
Proxic hat geschrieben:Der sollte ja eigentlich groß genug für alles sein, sogar bestimmt auch für die allermeisten Bilder. Ich berechne ja auch schon die Größe der einzelnen Dateien und die liegen alle bei < 50000. Da wird also auch nichts abgeschnitten. Sehr beunruhigend übrigens das du sagst es sieht alles gut aus. Da habe ich lieber einen Fehler ..
Ich habe keine Ahnung, wie groß FILE_BUF ist. Ich habe keine Ahnung, was drumrum ist, ich kann nur kommentieren, was Du postest.
Proxic hat geschrieben:Das einzige was ja höchstens noch von Relevanz ist, dürfte doch das öffnen der Datei sein oder nicht? Das sieht so aus

Code: Alles auswählen

int resource = open(path, O_RDONLY);
und den gebe ich dann an die Funktion send_resource weiter und der Rest davor ist ja nur noch Bestimmung des Pfades, Zugriffsrecht prüfen usw. und die Header scheinen ja auch in Ordnung zu sein. Da sollte ja kein Fehler vorhanden sein.
Sollte. :)

Testen kann ich es aber nicht.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Zenerid
Beiträge: 38
Registriert: Do Feb 05, 2015 4:15 pm

Re: Dateiübertragung über Socket funktioniert nicht richtig?

Beitrag von Zenerid » Mi Mai 11, 2016 1:55 am

Entschuldigung für die extrem späte Rückmeldung aber ich hatte die letzten Wochen wenig Zeit und ich habe auch hier und da noch was verbeesert aber soetwas ganz alleine zu machen ist auch nicht gerade wenig Arbeit. ;)
Das Problem war wohl auch übrigens ein Nullbyte, was sich eingeschlichen hatte. Das hatte ich irgendwie komplett übersehen aber ich bin auch kein informatiker oder Auszubildender in dem Bereich, obwohl ich solche technischen Themen schon sehr interessant finde.

Da ist jetzt mittlerweile auch übrigens schon einiges drum, nur um das mal so zu sagen. Da steckt ja jetzt auch doch schon einiges an Arbeit drin. Ich habe jetzt immer noch ein kleines Problem mit der Übertragung. Jetzt ist es nämlich so, dass zwar alles richtig dargestellt wird aber irgendwie habe ich manchmal das Problem, dass das Programm bei der Zeile write .. einen Fehler zurückgibt, also -1. Siehst du oder jemand anders da vielleicht einen Fehler? Das Programm stürtzt zwar nicht ab aber es kommt schon dieser Fehler und er beendet dann das Programm. Ich habe die Funktion ja jetzt auch ein wenig umgebaut, da es ja wohl sein kann, dass nicht alles auf einmal gelesen / geschrieben wird, dem ist doch so?

So sieht das jetzt derzeit aus:

Code: Alles auswählen

int send_resource(int sockfd, int res, int file_size) {
    char *ptr;
    char buf[file_size];
	memset(buf, 0, sizeof(buf));

	int bytes_read;
	int bytes_to_write = 0;
    ptr = buf;
    while((bytes_read = read(res, ptr, sizeof(buf) - bytes_to_write)) != 0) {
		if(bytes_read < 0) {
			exit(1);
		}
		ptr += bytes_read;
		bytes_to_write += bytes_read;
    }

    ptr -= bytes_to_write; // Anfang
    while(bytes_to_write > 0) {
    	int bytes_written = write(sockfd, ptr, bytes_to_write);
    	if(bytes_written <= 0) {
    		exit(1);
    	}
    	ptr += bytes_written;
    	bytes_to_write -= bytes_written;
    }

    return 1;
}
file_size ist die Größe der Datei, die ich jetzt immer auch mit stat hole und an die Funktion weitergebe. Der FILE_BUF war ja vorher nur temporär, weil ich die Berechnung mit stat noch nicht hatte. Der Rest ist ja wie gehabt. Ich habe mir auch noch einmal ptr genauer angeschaut und den ganzen Quatsch habe ich jetzt entfernt. Das mit dem malloc war ja wirklich komplett überflüssig. Der Fehler den ich bei der Zeile kriege ist:

Code: Alles auswählen

No source available for "__write_nocancel() at ...
Hast du da vielleicht so eine Idee, woran das liegen könnte? Vielleicht habe ich ja jetzt was mit dem ptr falsch gemacht?

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Dateiübertragung über Socket funktioniert nicht richtig?

Beitrag von Xin » Mi Mai 11, 2016 10:21 am

Zenerid hat geschrieben:aber ich bin auch kein informatiker oder Auszubildender in dem Bereich, obwohl ich solche technischen Themen schon sehr interessant finde.
Ein Informatiker oder FIAE lernt auch nicht ernsthaft programmieren. :D
Das ist meist Learning-by-Doing.
Zenerid hat geschrieben:Da ist jetzt mittlerweile auch übrigens schon einiges drum, nur um das mal so zu sagen. Da steckt ja jetzt auch doch schon einiges an Arbeit drin. Ich habe jetzt immer noch ein kleines Problem mit der Übertragung. Jetzt ist es nämlich so, dass zwar alles richtig dargestellt wird aber irgendwie habe ich manchmal das Problem, dass das Programm bei der Zeile write .. einen Fehler zurückgibt, also -1. Siehst du oder jemand anders da vielleicht einen Fehler? Das Programm stürtzt zwar nicht ab aber es kommt schon dieser Fehler und er beendet dann das Programm. Ich habe die Funktion ja jetzt auch ein wenig umgebaut, da es ja wohl sein kann, dass nicht alles auf einmal gelesen / geschrieben wird, dem ist doch so?
Halte ich für eher unwahrscheinlich, wenn Du während der Laufzeit des Programms nicht Festplatten oder USB-Sticks entfernst. Es sollte also alles in einem Rutsch funktionieren.
Zenerid hat geschrieben: file_size ist die Größe der Datei, die ich jetzt immer auch mit stat hole und an die Funktion weitergebe. Der FILE_BUF war ja vorher nur temporär, weil ich die Berechnung mit stat noch nicht hatte. Der Rest ist ja wie gehabt. Ich habe mir auch noch einmal ptr genauer angeschaut und den ganzen Quatsch habe ich jetzt entfernt. Das mit dem malloc war ja wirklich komplett überflüssig. Der Fehler den ich bei der Zeile kriege ist:

Code: Alles auswählen

No source available for "__write_nocancel() at ...
Eigentlich sieht die Funktion gut aus, was bedeutet, dass mir nichts direkt ins Auge fällt.

Aber den Fehler verstehe ich nicht: Wo bekommst Du diese Fehlermeldung her!?
Zenerid hat geschrieben:Hast du da vielleicht so eine Idee, woran das liegen könnte? Vielleicht habe ich ja jetzt was mit dem ptr falsch gemacht?
Das mit ptr erscheint mir alles zu passen.
Im Verdacht hätte ich eher, dass Du eine Binärdatei als Textdatei geöffnet hast. Womit ich mal vorsichtig abfrage, ob Du auf Windows oder einem Unix entwickelst?

Es könnte sein, dass dadurch die Größe der Datei von den Anzahl der eingelesenen Bytes abweicht und dadurch was durcheinander gerät.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Antworten