Avatar billede soreno Praktikant
15. januar 2003 - 19:56 Der er 17 kommentarer og
1 løsning

Send fil

Jeg er ved at lege lidt med en socket connection. Formålet er at lave et lille program der kan sende en fil, uafhængig af størrelsen, til et modtager program (som er lavet).

Flowet er således:
åbn connection
sendFile("file.bin");
luk connection

Det er min opfattelse at man laver ét kald til send når man vil sende data via en (TCP)socket - er det korrekt ?

At læse hele filen ind i RAM og derefter sende den må da kunne optimeres - det er da ihvertfald ikke sjovt at skulle sende 1GB.. ?

void sendFile(char *fileName)
{
    FILE *file;
    file = fopen(fileName, "rb");
    if(file)
    {
        fseek(file, 0, SEEK_END);
        int fileLength = ftell(file);
        fseek(file, 0, SEEK_SET);
       
        unsigned char *buffer = new unsigned char[fileLength];
        fread(buffer, sizeof(char), fileLength, file);
        fclose(file);

        if(send(dest_socket, buffer, fileLength, 0) == -1)
        {
            printf("*error* - could not send\n");
        }
        else
        {
            printf("*success* - sent %i bytes\n", fileLength);
        }
    }
}

Nogle forslag/links til andre måder at lave det på ?
Avatar billede -mundi- Nybegynder
15. januar 2003 - 20:03 #1
Hvorfor sender du ikke bare små bider af gangen, og læser direkte fra disken ?
Avatar billede soreno Praktikant
15. januar 2003 - 20:05 #2
Joow, det har jeg skam også overvejet - men endnu ikke prøvet.
Nogen der har et forslag til "pakke størrelse" ?
Avatar billede arne_v Ekspert
15. januar 2003 - 22:40 #3
Loop og send mindre bidder.

16384 / 32768 / 65536 bytes var måske passende størrelser.
Avatar billede arne_v Ekspert
15. januar 2003 - 22:42 #4
Endnu en grund til at loope er at send returnerer -1 ved fejl,
men eller antal bytes sendt. Og jeg har ikke kunnet findet
noget sted, hvor der garanteres, at den enten returnerer -1
eller det antal bytes du har bedt den sende.
Deraf kunne man frygte at ihvertfald nogle implementationer ville
kun sende en mindre bid. Hvorfor man alligevel skal loope.
Avatar billede arne_v Ekspert
15. januar 2003 - 22:45 #5
Ups.

Ikke helt rigtigt. Jeg har lige fundet en side som hævder:
    If the    message    is too long to
    pass atomically through the underlying protocol, then the error EMSGSIZE
    is    returned, and the message is not transmitted.
Avatar billede arne_v Ekspert
15. januar 2003 - 22:50 #6
Og det antyder også at den implementation ikke vil
kunne lide for store bidder.

[det er en Unix man page - jeg har hapset det fra]

Så måske skulle du nøjes med 1024 (ihvertfald under 1500).

Så den del af mit svar var også forkert !

:-(
Avatar billede arne_v Ekspert
15. januar 2003 - 22:52 #7
Noget helt andet: hvorfor bruger du ikke stat/fstat i.s.f.
fseek+ftell ?
Avatar billede soreno Praktikant
16. januar 2003 - 06:54 #8
Hmmm - er det kun mig der kan se 5 tomme svar/kommentarer ?
Avatar billede soreno Praktikant
16. januar 2003 - 06:59 #9
Nå, men jeg har indtil videre løst det ved at sende 1024 bytes ad gangen.
Det giver dog lidt problemer da jeg godt kunne tænke mig at medsende en md5 sum af filen - så jeg kan verificere filen ved modtagelsen. Det virker ihvertfald lidt dumt at læse hele filen først - for at kunne generere en md5 - for dernæst at sende den i små bidder.
Avatar billede soreno Praktikant
16. januar 2003 - 19:48 #10
Arne >> kan du skrive med usynlig skrift ?
:-)
Avatar billede arne_v Ekspert
16. januar 2003 - 22:18 #11
Det er en eksperten fejl !

:-)
Avatar billede arne_v Ekspert
16. januar 2003 - 22:21 #12
Jeg skrev lidt frem og tilbage.

Og fandt dokumentation for at send sender alle byte atomisk
i forhold til den underliggende protokol *eller* giver fejl.

Og konklusionen var derfor at du skulle holde dig under
det den underliggende protokol kan klare. Og det er hvis jeg
husker rigtigt 1536 bytes minus overhead.

Så 1024 er sikert et godt valg.
Avatar billede arne_v Ekspert
16. januar 2003 - 22:22 #13
Og kan du ikek løse 2 gennemløsb problemet ved at sende
MD5 til sidst ?

(modtageren kan vel alligevel ikke checke før han har læst
hele filen)
Avatar billede soreno Praktikant
17. januar 2003 - 11:23 #14
"hvorfor bruger du ikke stat/fstat i.s.f.
fseek+ftell ?"
Fordi programmet skal virke med Windows og Linux - og mig bekendt findes stat/fstat ikke på Windows ?


"Og kan du ikek løse 2 gennemløsb problemet ved at sende
MD5 til sidst ?"
Tjooo, jeg kunne vel update min digest for hver buffer jeg sender og gøre det samme ved modtagelsen. Det vil jeg prøve.
Avatar billede arne_v Ekspert
17. januar 2003 - 13:27 #15
Så vidt jeg kan se så har både mingw og VC++ 6 stat.h !
Avatar billede soreno Praktikant
17. januar 2003 - 14:15 #16
Okie, det var jeg ikke klar over - jeg læste blot at stat ikke var "ANSI C" og derfor regnede jeg ikke med den fantes til anden end *nix.

Men så må jeg jo spørge: "Er der nogen fordel ved at bruge stat frem for fseek ?"
Avatar billede arne_v Ekspert
17. januar 2003 - 14:23 #17
Den er ikke ANSI C standard.

Men den er POSIX standard.

(nu er Windows ikke POSIX compliant, så det betyder ikke at
den er til Windows)

Den har tilsyneladende været så udbredt at MS har valgt at tage den med.
Avatar billede arne_v Ekspert
17. januar 2003 - 14:27 #18
Om der er nogen fordel ved stat/fstat fremfor fseek/ftell ?

Effektivitetmæssigt tror jeg ikke, at der den store
forskel, da jeg formoder, at fseek end stort set laver
det samme som stat/fstat.

(det ville ihvertfald være en meget bøvet implementation at læse hele
filen !)

Men jeg synes måske at koden var nemmere at forstå med
fstat og st_size.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester