C files einlesen
-
Hast du dir mal die übertragenen Daten angesehen (mit printf)?
Was wird da denn hin und her geschickt?
Ist da noch ein \r\n in rcvmes?printf("rcvmes :<%s>\n", rcvmes);
Durch die <> kannst du ein \n erkennen.
-
also
printf("rcvmes :<%s>\n", rcvmes);
liefert:
rcvmes :<GET ff.txt >
Also bei der Eingabe wird die Bestaetigung (also das "\n") noch drangehaengt oder?
wie kann man dass den wegschneiden?
-
Typ222 schrieb:
rcvmes :<GET ff.txt >
Also ist sogar zweimal ein \n und/oder \r drin. Die solltest du noch rausschmeissen. (mit strrchr() geht das ganz gut)
-
Immer wieder dasselbe: strtok ist nichts für Anfänger!
Was tust du, falls der Dateiname Leerzeichen enthält? (Anfänger und Theoretiker würden jetzt antworten: kommen bei mir nie vor)
Wo gibst duchar *file_name = malloc(sizeof(char) * 30);
wieder frei?
Für fopen()==NULL gibt es die aussagekräftige Varianteperror(file_name)
.
recv ist kein C Standard, du musst sicherstellen, dass hier nicht ein '\0' in den Nutzdaten vorkommen kann, außerdem solltest du recv in einer while-Schleife abfragen und den String zusammensetzen.
Für deinen Anwendungsfall ist strtok ungeeignet, viel besser wäre strncmp bzw. sscanf, also z.B.if( !strncmp(rcvmes,"GET ",4) ) puts(rcvmes+4);
oder
if( 1==sscanf(rcvmes,"GET %[^\n]",filename) ) puts(file_name);
-
sscanf ohne Längenbegrenzung auf aus dem Netzwerk gelesene Daten? Du bist ja völlig übergeschnappt. Von Buffer-Overflows noch nichts gehört, was?
Nein, strtok bzw. strtok_r o.ä. (strtok ist nicht reentrant) ist hier schon sinnvoller. Denkbar wäre beispielsweise
char *filename; if(strncmp("GET ", request, 4) == 0 && (filename = strtok(request + 4, "\r\n"))) /* kein eigener Buffer notwendig! */ { FILE *fd = fopen(filename, "r"); /* ... */ fclose(fd); }
Ganz abgesehen von all diesen Vorschlägen muss ich aber sagen: generell ist es beim Verarbeiten von Daten aus dem Netzwerk sinnvoll, so paranoid wie möglich an den Datensatz heranzugehen. Ich sähe an deiner Stelle davon ab, mir hier eine solche Frickellösung zusammenzuhacken; stattdessen muss eine vernünftige Sprachspezifikation und ein sie umsetzender Parser her. Kennst du dich mit formalen Sprachen aus?
-
Danke fuer die Antworten...
@seldon:
Bei strtok(request + 4, "\r\n") wird aber nicht beruecksichtig, dass <GET <filename> xy> auch nicht vorkommen darf oder?
Wir muessen eben alle Faelle abdecken deswegen das herumgeschnipsel
-
So, wie es da steht, fasst es alles, was nach GET bis zum Ende der Zeile kommt, als Teil des Dateinamens auf. Leerzeichen können in Dateinamen ja auch vorkommen.
Wenn das nicht gewollt ist, splitte statt nach "\r\n" halt nach " \r\n". (Leerzeichen in die Menge aufgenommen)
Allerdings: wie gesagt, eigentlich sind derartige Dinge Fälle für sauber definierte Parser - abhängig von der Komplexität des Protokolls kann man vielleicht mit Regexes auskommen, aber mit einfachen String-Funktionen da ranzugehen, ist ziemlich gefährlich. Ich gehe so weit, es in Netzwerkanwendungen als unverantwortlich zu bezeichnen.
-
seldon schrieb:
sscanf ohne Längenbegrenzung auf aus dem Netzwerk gelesene Daten? Du bist ja völlig übergeschnappt. Von Buffer-Overflows noch nichts gehört, was?
Du könntest dich auch mal wieder auf die Netiquette besinnen und deine Verbesserungen in sachliche Worte fassen. Hat dich hier niemand angepisst, oder?
sscanf() auf die die überprüfung von <Get > anzusetzen muß kein Sakrileg sein, wie du es ausdrückst. Die Längenbegrenzung folgt aus MAX_BUFFERS für rcvmes.
Schwache Leistung
-
forenseeker schrieb:
Schwache Leistung
Nee, seldons Beiträge lese ich immer gerne, seine Kenntnis ist unbestritten.
Wutz hat sich aber seinerseits des Öftereren gegenüber "Newbies" im Ton vergriffen, wenn es sich um einen anderen User gehandelt hätte, wäre der Ton in seldons Post mit Sicherheit milder.
-
Ich hätte das freundlicher formulieren können, mea culpa. Den Vorwurf, dass mein Ton mit der Person Wutzs zusammenhängt, muss ich mir auch gefallen lassen; er ist mir in der Tat mehrfach negativ aufgefallen. Das ist aber natürlich keine Entschuldigung.
In der Sache ist sscanf trotzdem eine gefährliche Wahl, und im konkreten Fall hilft dir auch MAX_BUFFER nicht weiter, weil MAX_BUFFER deutlich größer ist als der für filename allozierte Speicher. Man könnte sich hier mit
if(1 == sscanf(rcvmes, "GET %29[^\n]", filename)) { /* filename hat 30 Byte Platz */ puts(file_name); }
behelfen, aber ich sehe wirklich keinen Grund dazu, die Länge des Dateinamens auf diese Weise künstlich zu beschränken. Außerdem kann es bei Netzwerkkommunikation leicht passieren, dass nicht \n, sondern \r\n oder \r als Zeilenumbruch übermittelt wird - \r\n taucht in einer ganzen Reihe RFCs auf, beispielsweise RFC 822 (E-Mail) und RFC 2616 (HTTP) - so dass die Beschränkung auf \n als Zeilenumbruchszeichen problematisch sein kann. Auch dass lässt sich leicht beheben (%29[^\r\n]), aber die völlig unnötige Längenbeschränkung und der zusätzliche Rechenaufwand bleiben.