Oppure

Loading
15/08/11 23:38
Danyez
Salve, ragazzi !
Mi vedo costretto ad usufruire della vostra gentilezza chiedendovi un aiuto.

Ho creato un file server.c ed un file client.c perfettamente funzionanti. Il file client.c invia un determinato buffer al file server.c che, ricevendolo, lo inserisce in un file di testo chiamato buffer.txt

Fin qui tutto bene, fino al momento in cui non ho deciso che non mi bastava :P .. ho tentato innanzitutto l'invio di un buffer più grande di 8 kb (limite massimo buffer) ed ho scoperto con mio grande piacere che l'applicazione comunque riceveva tutto il buffer (diviso in porzioni di 8 kb). Poi ho deciso di utilizzare un vecchio esperimento che feci (un semplice copia-incolla in C, un'applicazione che copia byte per byte l'intero file e lo riscrive) applicato a questo progetto : l'invio di un file jpeg sottoforma di stream e la riscrittura da parte di server.c in un file di nome buffer.jpg. Qui sono nati i miei problemi.

Questa è la parte di codice, in Client.c, che legge il file e lo memorizza in un buffer.
    FILE *fsource;
    ..
    ..
    ..
    int filesize;
    if ((fsource = fopen(argv[3],"r")))
    {
    fseek(fsource, 0, SEEK_END); //sposto cursore alla fine
    filesize = ftell(fsource);
	printf("Lunghezza file : %d \n",filesize); //leggo posizione cursore per lunghezza file
    char buffer[filesize]; //dichiaro buffer della grandezza del file
    fseek(fsource, 0, SEEK_SET);
    fread(buffer,sizeof(buffer),1,fsource);


Questa è la parte di codice, in Client.c, che invia il buffer.
send(sock,buffer,sizeof(buffer),0);



Questa è la parte di codice, in Server.c, che ricostruisce lo stream creando il file buffer.jpg
FILE *ftext;
	int carat;
	while ((carat=recv(sd_client, buff, sizeof(buff), 0))>0)
{
	ftext = fopen("buffer.jpg","a+");
	printf("Dati ricevuti. \n");
	fwrite(&buff,strlen(buff),1,ftext);	
	char *ip_address = inet_ntoa(client_addr.sin_addr);
	printf("IP: %s\n", ip_address);
	printf("------------------------\n");
}
fclose(ftext);


Il risultato che ottengo è un file di 1,1 kb ovviamente non leggibile. La cosa non ha il minimo senso, poichè cambia praticamente pochissimo dal codice per il passaggio di un testo (e ripeto, ho provato ad inviare con un ciclo for un ammontare di 'A' pari a 400 kb di buffer e non ho avuto il minimo problema !).

La domanda principale è : Perchè si comporta in questo modo ?

Vi sarò enormemente grato se vorrete aiutarmi :)

------------------------------------------------------------------------------------------------------------
AGGIORNAMENTI :

Ringrazio chiunque abbia letto anche solo per un attimo il mio thread bruciando qualche neurone in suo onore, rendendo noto che ho risolto il problema.


Avevo già intuito, ieri notte, che il problema fosse dato dalla lettura dello stream in cui vi era la possibilità di incontrarne una parte (erroneamente) identificata come fine stringa. Ho quindi deciso di adottare un sistema che leggesse lo stream e lo copiasse carattere per carattere in modo da non andare incontro al problema. Lascio qui la soluzione nel caso qualcuno ne avesse bisogno :)


Codice modificato in : client.c
for (n=0;n<filesize;n++) {
   a[0]=buffer[n];
   send(sock,a,1,0);
}


Codice modificato in : server.c
while ((carat=recv(sd_client, buff, sizeof(buff), 0))>0)
{
	for (nb=0;nb<carat;nb++)
{
	ftext = fopen("buffer.jpg","ab");
	b[0] = buff[nb];
	fwrite(b,1,1,ftext);
	fclose(ftext);
}
}


Il codice è ovviamente ancora un pò da sistemare e ripulire, ma comunque sia è questo il metodo che ho usato per risolvere il problema. :D


Grazie a tutti, comunque ! :k: :k:
Ultima modifica effettuata da Danyez 16/08/11 8:14
aaa
16/08/11 8:10
comina8
Avevo implementato qualcosa di simile anch'io..
Il modo migliore per farlo è leggere pezzi di file e inviarli.

Prima di tutto il tuo server non sa di quanti byte è composto il file, quindi riceve un array di N elementi che non è detto siano uguali alla grandezza del file.
Seconda cosa per i file più grossi (film o altro) non sarebbe possibile fare come hai fatto tu...

Fino a ftell(..) è corretto, dopo di questo devi inviare al server la grandezza del file

int Lun=ftell(fp);
send(sock,&Lun,sizeof(int),0);

recv(sock,&Lun,sizeof(int),0);

Poi esegui un for che va da i=0 fino a i<(Lun/LUNGHEZZA_MASSIMA).

LUNGHEZZA_MASSIMA è una define che dev'essere UGUALE sia nel server che nel client.

Dentro il ciclo leggi fread(array,LUNGHEZZA_MASSIMA,sizeof(char),fp);
elementi e li invii al server send(sock,array,LUNGHEZZA_MASSIMA,0);

recv(sock,array,LUNGHEZZA_MASSIMA,0);

Una volta uscito dal for ti chiedi se i%LUNGHEZZA_MASSIMA non è uguale a zero (se ci sono dei byte nel file rimasti) e leggi fread(array,i%LUNGHEZZA_MASSIMA,sizeof(char),fp); e invii al server, che eseguirà lo stesso controllo (visto che sa anche lui la lunghezza).

Chiudi il file e dovrebbe esserci tutto.
Per iniziare LUNGHEZZA_MASSIMA impostala a 512 che va abbastanza bene, inviando troppi byte per volta va fin più lento...

PS: l'array dichiaralo di LUNGHEZZA_MASSIMA...

PPS: se il file fosse più piccolo di lunghezza massima ti conviene eseguire un controllo (LUNGHEZZA_MASSIMA impostalo come normale unsigned long)

#define MAX 512
if(LunghezzaFile<MAX)
LUNGHEZZA_MASSIMA=1; //tanto se è più piccolo di mezzo mb te lo invia in un attimo
else
LUNGHEZZA_MASSIMA=MAX;

char Array[MAX];
Ultima modifica effettuata da comina8 16/08/11 8:17
aaa