Newsgroup: it.comp.os.linux.development
Titolo: send,recv,read,write

Salve a tutti.
Sto facendo una applicazione, in C naturalmente, full threaded sotto
piattaforma Linux kernel 2.6.16 gcc 3.3.6 che deve implementare da una
parte un server e dall'altra un client. Il server deve permettere la
navigazione e il "putting" dei file. Un "clone" di ssh sostanzialmente
con
il filetransfer incorporato. Tutto ok diciamo, finchè non mi trovo ad
implementare il filetransfer. Il punto è che ho risultati
IMPREVEDIBILI.
Alcune volte i file vengono trasferiti correttamente, altre volte
vengono
trasferiti solamente alcuni byte, altre volte vengono corrotti (stesso
numero di byte ma con un md5sum differente), altre volte il
trasferimento
non avviene minimamente. E ho notato che quasi sempre l'errore risiede
nelle write() che a destinazione fa il server.
Premetto che il server scambia messaggi SOLO sulla porta 5000 e i dati
SOLO sulla 5001. Il client può bindarsi le porte dove vuole, sia per i
messaggi che per i dati.
Ecco il codice lato server:
	int o;
	int rc;
	unsigned long long int counting=0; //contatore byte scritti
	unsigned long long int counting_r=0; // contatore byte
ricevuti 
	struct data_flow recv_data;
	/* Struct data_flow è così implementata: struct data_flow {
		char data[PK_LEN];// i dati PK_LEN = 128 
		short last; // se è settato a 1 vuol dire che è
l'ultimo "pacchetto" 
		int dim_pkt; // la dimensione dei dati presenti su
data[PK_LEN]
	};
	*/
	memset(&recv_data,0,sizeof(struct data_flow));
 
	rc=recv(fd, &recv_data, sizeof(struct data_flow),0);
 
	while (rc > 0) {
		counting_r += rc;
 
		if
((o=write(fd_f,recv_data.data,recv_data.dim_pkt))<recv_data.dim_pkt) {
			if (o<0){
				perror("write");
				//getchar();
			}
			else {
				printf("Write only %d out of %d
bytes\n",o,recv_data.dim_pkt);
				//getchar();
			}
 
		}
 
		printf("%d bytes wrote\n",o);
		counting += o;
 
		if(recv_data.last == TRUE) {
			printf("Last Packet!\n");
			break;
		}
		memset(&recv_data,0,sizeof(struct data_flow));
		rc=recv(fd, &recv_data, sizeof(struct data_flow),0);
	}
 
	close(fd_f);
 
	close(fd_f);
 
	if ( shutdown(fd,SHUT_RDWR) == -1 ){
		perror("handle_connection_data() : shutdown() failed
");
		strerror(errno);
		exit(-1);		
	}
Ecco il codice lato client:
		unsigned long long int counting= 0;
		int o;
 
		while ((tosend.dim_pkt=read(fd_S, tosend.data,
PK_LEN))>0 && tosend.last == FALSE) {
 
			if(tosend.dim_pkt < PK_LEN) tosend.last =
TRUE;
			else tosend.last = FALSE;
 
			if ((o=send(data_socket,&tosend,sizeof(struct
data_flow),0))<tosend.dim_pkt) {
				if (o<0){ 
					perror("send");
				}
				else {
					printf("Sent only %d out of %d
bytes\n",o,tosend.dim_pkt);
				}
 
			}
 
			counting += o;
 
			//printf("%d bytes sent\n",o);
 
			memset(&tosend,0,sizeof(struct data_flow));
		}
		close(fd_S);
		if ( shutdown(data_socket,SHUT_RDWR) == -1 ){
			perror("data_thread() : shutdown() failed ");
			strerror(errno);
			exit(-1);
		}
Grazie in aticipo a chi mi vorrà aiutare.
Ciao!	

 Ciao!
La funzione recv() restituisce il numero di bytes ricevuti, e non sempre
sono esattamente quelli che richedi, ma possono essere in numero
inferiore. Nel programma non mi sembra che esegua di quanto ricevuto , ma
scrivi comunque per una dimenzione fissa della struttura.
Dovresti cambiare il programma scrivendo solo quello che "effettivamente"
ricevi.
Ciao
MrBig 
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 
Innanzitutto ti ringrazio per risposta.
Allora, forse qualcosa non mi torna.
Sia read,write,send,recv non garantiscono che tutto quello del quale si fa
richiesta venga effettivamente fornito.
Ma se devo trasferire un file a blocchi di N byte, come posso riuscire?
Client:
Leggo N BYTE dal file, Spedisco N BYTE sul socket
Server:
Ricevo N BYTE dal socket , Scrivo N BYTE sul file
Se una di queste operazioni non legge/scrive/riceve/invia N BYTE, come
posso rimediare? Se avessi ricevto N-2 BYTE invece che N BYTE, e se
chiedessi i rimanenti 2 BYTE facendo una richiesta da 2, il client quali
byte mi spedisce? i primi 2 del blocco successivo o i 2 che non mi ha
inviato?
Spero di essere stato abbastanza chiaro nello spiegare i miei dubbi.
Un saluto.

 Un saluto.
Non esiste questa possibilità, l'unica è che ti ricostruisci i blocchi con
quanto ti viene inviato.
Comunque perchè complicarti la vita, per avere l'indicazione di fine file
che ti riporti nella struttura?
Quando il sender ha terminato di scrivere ed esegue la chiusura del
socket,  al receiver viene restituito 0 alla successiva chiamata di recv().
Spero che sia stato chiaro.
Saluti
