Newsgroup: it.comp.os.linux.development
Titolo: Ricezione di file con connessione tcp/ip

Ciao a tutti
Utilizzando un programmino che fa da server sto cercando di ricevere
un file di testo da un client che momentanamente viene inviato da un
pc con hyperterminal
la parte di programma destinata alla ricezione è questa:
        listen (sd, 20);
        while(1)
        {
                if ((temp_sd= accept(sd, (struct sockaddr *)&client,
&address_size)) <0)
                         printf("Errore nella chiamata ACCEPT\n");
                /*Ricevo i dati dal client */
                recv(temp_sd,&buff,sizeof(buff),0);
                printf("Dati ricevuti %s\n\n\n\n",buff);
                //strcpy(buff,"Tutto OK!");
                //send(temp_sd,&buff,strlen(buff),0);
                close(temp_sd);
        }
Buff è un unsigned char buff[500]
Il file che tento di ricevere è
<!-- saved from url=(0022)
http://internet.e-mail
 -->
<html>
<head>
<title>TRATTAMENTO NON ABILITATO</title>
</head>
<body>
</body>
</html>
e quello che ricevo è
Dati ricevuti <!-- saved from url=(0022)
http://interne?PW5?|???|
???yV5 nV5X(W5 
spero di essermi spiegato bene!
grazie anticipatamete per l'aiuto

>                 recv(temp_sd,&buff,sizeof(buff),0);
se buff č gią u puntatore, perchč passi alla recv il suo indirizzo?

 se buff è già u puntatore, perchè passi alla recv il suo indirizzo?
errore di stampa...


ma il problema rimane lo stesso

 ma il problema rimane lo stesso
Se buff e' un puntatore con questo codice ricevi al massimo la lunghezza 
del puntatore, cioe' 4 bytes su un sistema a 32bit e 8 su un sistema a 
64bit :)
Posta il codice completo.
---
Bye,
  Gabry

On 3 Mag, 17:29, Gabriele Greco

io con i puntatori non ho mai avuto molta confidenza...... allora
metto tutta la codifica eccola qua.
#include <stdio.h>
#include<string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
int main(void)
{
	unsigned char buff[500];
	struct sockaddr_in server;
	struct sockaddr_in client;
	int sd, temp_sd;
	int address_size;
	unsigned short port = 9000;
	/*int i;
	if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		printf("Errore nella craazione del server!\n");
	server.sin_family = AF_INET;
	server.sin_port = htons(port);
	server.sin_addr.s_addr = INADDR_ANY;
	/* assegnamo al socket un processo tramite la funzione BIND */
	if (bind(sd, (struct sockaddr *)&server, sizeof(server)) < 0)
		printf("Errore nella chiamata di sistema BIND!\n");
	listen (sd, 20);
	while(1)
	{
		if ((temp_sd= accept(sd, (struct sockaddr *)&client, &address_size))
<0)
        		 printf("Errore nella chiamata ACCEPT\n");
		/*Ricevo i dati dal client */
        	recv(temp_sd,buff,sizeof(buff),0);
        	printf("Dati ricevuti %s\n\n\n\n",buff);
		//i=0;
		/*while (i < 500)
		{
			printf("%c",buff[i]);
			i++;
		}*/
		close(temp_sd);
    	}
	return EXIT_SUCCESS;
}

         	recv(temp_sd,buff,sizeof(buff),0);
Ok, qui dovresti controllare quanti bytes leggi e quando hai finito di 
leggere "tappare" il tuo buffer.
Se mandi tanti dati non e' detto che vengano mandati come pacchetto 
unico, ma potrebbero essere spezzati, quindi devi avere un modo dal 
client per notificare la fine della lettura (o trasmetti la dimensione 
del blocco prima dei dati o chiudi la connessione una volta trasmessi).
Esempio (non testato ma che dovrebbe darti l'idea):
		int total = 0;
		for(;;) {
			int len = recv(temp_sd,buff + total,sizeof(buff) - total - 1,0);
			if (len <= 0 || (total + len + 1) >= sizeof(buff)) // esco dal loop 
in caso di disconnessione o buffer pieno
				break;
 
			total += len;
		}
		buff[total] = 0; // metto il terminatore
Bye,
  Gabry

On 4 Mag, 09:13, Gabriele Greco

ok o capito il ragionamento ma non ho ben capito cosa fa ora la
funzione recv e cosa controlla l'if successivo

 funzione recv e cosa controlla l'if successivo
recv si occupa di riempire il buffer in base anche a piu' ricezioni 
consecutive di parti del testo che trasmetti. Per far cio' si somma al 
buffer l'offset dei bytes gia' ricevuti.
len <= 0 significa un errore o una disconnessione dell'host remoto, in 
questo caso si esce dal loop.
Bye,
  Gabry

On 4 Mag, 11:44, Gabriele Greco

credo di avere capito grazie per l'aiuto

On 4 Mag, 12:44, Gabriele Greco

Ho potuto provare solo oggi perche ho avuto problemi con il pc, ma ora
non mi viene mai stampato nulla...


o meglio se tento di ricevere il file di prima non mi arriva nulla se
invece provo a ricevere questo :
<!-- saved from url=(0022)
http://internet.e-mail
 -->
<html>
<head>
<title>RITIRARE IL TICKET STAMPATO</title>
</head>
<body>
ANCONA GIUSEPPE
<h2>Cure</h2>
FANGO E BAGNO TERAPEUTICO
<h2>Data e Ora</h2>
10/03/2006  11:30
<h2>Reparto</h2>
Fanghi Cabina 12
<h2>Durata</h2>
Durata Fango: 15
Durata Bagno: 15
<h2>Sede di Trattamento</h2>
spalla post. destra
spalla post. sinistra
<h2>Terapia e Controindiz.</h2>
monitorare controllo della P.A.
<h2>Altre note Mediche</h2>
soggetto iperteso
</body>
</html>
ricevo sempre cose diverse:
<0/03/2006  11:302>EUTICO STAMPATO</title>e-mail -->net.e-mail -->
oppure
spalla post. dattamento</h2>AMPATO</title>e-mail -->net.e-mail -->
oltre a non ricevere tutto sembrerebbe che quello che viene
immagazzinato in buff sia disordinato

On 4 Mag, 12:44, Gabriele Greco
<gabrielegr...@REMOVEUPPERCASETOMAILtin.it> wrote:

con il file che ti avevo fatto vedere all'inizio non esce mai dal
ciclo for, o meglio non entra mai nell'if....
con il secondo file invece si disconnette l'host dopo poco oltre a
farmi ricevere quelle cose che ti ho postato nei messaggi precendeti

 farmi ricevere quelle cose che ti ho postato nei messaggi precendeti
Quando trasferisci via TCP devi utilizzare un meccanismo per stabilire 
quando il trasferimento e' finito, perche' TCP e' uno stream, quindi non 
c'e' una dimensione del messaggio prestabilita.
Quindi le possibilita' che hai sono fondalmentalmente 2 (HTTP per dire 
le implementa entrambe).
1) Trasmetti la lunghezza del messaggio prima del messaggio stesso.
2) Chiudi la connessione lato client quando hai finito di trasmettere il 
tuo pacchetto.
Il codice d'esempio postato supponeva la 2. Ovvio che se lato client non 
chiudi la connessione lato server rimani nel loop.
Per quanto riguarda il contenuto del pacchetto occhio ad incrementare 
"total" con il numero di bytes ricevuti dopo ogni recv() ed in uscita 
dal loop a "tappare" il tuo buffer con il terminatore della stringa (0).
Cmq ti consiglio di cercarti un libro che parli del TCP/IP o qualche 
tutorial esauriente in rete, le problematiche sono molte ed e' difficile 
affrontarle tutte in un NG :)
---
Bye,
  Gabry

On 9 Mag, 11:53, Gabriele Greco

allora sono riuscito a ricevere tutti e due i file che mi interessano,
l'unico problema e che per farlo ho dovuto scrivere tutto il file di
testo si di una riga sola, altrimenti la ricezione risulta incasinata
nel senso che ongi qual volta riceve un fine riga e un a capo
imagazzina in buff cose assurde cancellado parti di quello che aveva
gia salvato, a me però piacerebbe avere la suddivisione

 
il sorgente?
-- 
SF
"Spartani... mangiate tanto a colazione perchč stasera ceneremo nell'Ade!!"

 "Spartani... mangiate tanto a colazione perchè stasera ceneremo nell'Ade!!"
se intendi il mio codice eccolo qua (gaby ho cambiato la procedura che
mi avevi dato ma credo che sia equivalente giusto??)
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
int main(void)
{
        char buff[1024];
	char in[1024];
	struct sockaddr_in server;
        struct sockaddr_in client;
        int sd, temp_sd;
        int address_size;
        unsigned short port = 600;
        int len,i;
        if((sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
                printf("Errore nella craazione del server!\n");
        server.sin_family = AF_INET;
        server.sin_port = htons(port);
        server.sin_addr.s_addr = INADDR_ANY;
        /* assegnamo al socket un processo tramite la funzione BIND
*/
        if (bind(sd, (struct sockaddr *)&server, sizeof(server)) < 0)
        {
		printf("Errore nella chiamata di sistema BIND!\n");
		exit(-1);
	}
        listen(sd, 20);
	if ((temp_sd= accept(sd, (struct sockaddr *)&client,
&address_size))<0)
        {
		printf("Errore nella chiamata ACCEPT\n");
		exit(-1);
	}
	/*Ricevo i dati dal client */
	i=0;
	while(1)
	{
		len=recv(temp_sd,buff,sizeof(buff),0);
	    	if (len <= 0)//se non ricevo piu caratteri esco
	        	break;
		buff[len]='\0';
		if(i==0)
			strcpy(in,buff);
		else
			strcat(in,buff);
		i++;
		printf("%s\n",in);
	}
	printf("\n\n%s\n",in);
}

 mi avevi dato ma credo che sia equivalente giusto??)
no, non è giusto, la sua controllava anche lo sforamento dei buffer. Poi non 
capisco perchè devi usarne due, di dimensioni uguali peraltro: uno è più che 
sufficiente.

a parte il metodo che non mi piace, direi che il codice sembra giusto, se 
escludiamo sforacchiamenti vari dei buffer che non vengono controllati (strcpy 
e strcat non sono sicure da questo punto di vista, meglio le varianti strncpy 
e strncat).


 
Il codice del server mi sembra corretto, il dubbio rimane su cosa fa il 
client :)
Il fatto che ti "incasini" tutto se ci sono gli accapo non e' magari 
dovuto a come mandi gli accapo stessi?
Se mandi dei \r senza il \n su Linux l'effetto e' proprio quello di
scrivere ad ogni accapo sulla stessa linea, e se usi un terminale su 
windows potrebbe essere configurato proprio per mandare solo \r.
Inoltre il tuo programma fa sicuramente casino se provi a ricevere un 
buffer di dimensioni superiori ai 1024bytes.
Bye,
  Gabry

On 10 Mag, 10:35, Gabriele Greco

ho usato due buffer per fare una prova durante le mille modifiche che
ho fatto prima di capire che il problema era dovuto al file di testo e
non al server, pensavo ci fosse qulche errore nella fase di scrittura
dato che mi perdeva delle linee come avevo detto prima in effetti ora
sarebbe da levare.......
Per quello che riguarda il file di testo è un banale txt quindi non so
cosa dovrei modificare per il problema dell'andare a capo

dunque ho finalmente capito qual è il problema ma non so bene come
potrei risolverlo
quando la ricevo con la funzione recv una stringa con all'interno un
carattere CR (Carrieg Return) ed LF(line feed) che indiacano di
ricominicare dall'inizio in una nuova linea, ricomincia solamente
dall'inizio e mi incasina le stringa.... spero di essermi fatto capire

fede wrote:

ma di questo effetto quando te ne accorgi? quando vai a scrivere il buffer in 
un file, per caso?



no per testare ho messo delle printf allìinterno del while se noti
stampavo ogni volta la stringa in e analizzando accuratamente le
stampe mi sono reso conto di questo....