Newsgroup: it.comp.os.linux.development
Titolo: read & write interi da socket TCP

Vorrei scrivere e leggere un intero su un socket TCP. Quindi una cosa
del genere.
// SCRITTURA
int mess = 123;
uint32_t mess_nbo = htonl(mess);
int bytesent = write(newsockfd, &mess_nbo, sizeof(mess_nbo));
// LETTURA
uint32_t mess_nbo;
int bytesrecv = read(sockfd, &mess_nbo, sizeof(mess_nbo));
mess = ntohl(mess_nbo);
Il mio problema è che write e read non garantiscono di mandare tutto
il messaggio, quindi sono responsabile di rimandare la parte mancante.
Sempre se non erro..
Quindi mi sono creato 2 funzioni che cercano di fare questo, solo che
NON FUNZIONANO ;) Mi viene il dubbio che non posso fare una cosa del
genere, dato che mi sembrano corrette.
Qualcuno mi sa dire il come mai?
Ringrazio anticipatamente..
Ale
/*
 * Try to read the entire message from the socket
 */
int sockread(int sock, int *mess) {
	int readed = 0;
	int just_readed = 0;
	uint32_t mess_nbo;
	uint32_t *p = &mess_nbo;
	do {
		just_readed = read(sock, p + readed, 4);
		if (just_readed == -1) {
			return -1;
		}
		readed += just_readed;
		printf("Readed: %d/%d\n", just_readed, readed);
	} while ((just_readed > 0) && (readed < sizeof(uint32_t)));
	*mess = ntohl(mess_nbo);
	printf("%d - %d", *mess, mess_nbo);
	return readed;
}
/*
 * Try to write the entire message on the socket
 */
int sockwrite(int sock, int mess) {
	uint32_t mess_nbo = htonl(mess);
	int written = 0;
	int just_written = 0;
	uint32_t *p = &mess_nbo;
	do {
		just_written = write(sock, p + written, 1);
		if (just_written == -1) {
			return -1;
		}
		written += just_written;
		printf("Written: %d/%d\n", just_written, written);
	} while ((just_written > 0) && (written < sizeof(uint32_t)));
	return written;
}

                 just_written = write(sock, p + written, 1);
Un piccolo appunto: ho settato a 4 e a 1 i byte, solo per vedere come
reagiscono le cose in caso di invii parziali.
Nella versione finale andranno settati a sizeof(uint32_t)
Scusate il doppio messaggio..
Ale

 }
Ci sono problemi di puntatori in entrambe le funzioni, ma mi sembrano 
inutili.
Ciao
Giovanni
-- 
   A computer is like an air conditioner,
   it stops working when you open Windows.
   Registered Linux user #337974  < 
http://giovanni.homelinux.net/
 >


Ti sembrano inutili, nel senso che useresti read e write così come
sono?

 sono?
Se l'obiettivo i leggere un intero, si. Magari aggiungendo che non ci 
siano errori.


On 03/02/08 16:40, ale.ber wrote:

Se l'obiettivo è di leggere un intero, si. Magari aggiungendo i 
controlli che non ci siano errori.
Mi è rimasta qualche parola nella tastiera ;-)


Ora ho sistemato un po i puntatori.. cosa ne pensi? Ora il tutto
funziona.
Immagino che in condizioni normali una cosa del genere non serva, ma
il codice che scrivo è per un corso di Network Programming, quindi mi
devo fare le paranoie anche su queste cose. ^^
/*
 * Try to write the entire message on the socket
 */
int sockwrite(int sock, int mess) {
	int written = 0;
	int just_written = 0;
	char *p = (char *) &mess;
	do {
		just_written = write(sock, p + written, sizeof(int));
		if (just_written == -1) {
			return -1;
		}
		written += just_written;
		printf("Written: %d/%d\n", just_written, written);
	} while ((just_written > 0) && (written < sizeof(int)));
	return written;
}
/*
 * Try to read the entire message from the socket
 */
int sockread(int sock, int *mess) {
	int readed = 0;
	int just_readed = 0;
	char *p = (char *) mess;
	do {
		just_readed = read(sock, p + readed, sizeof(int));
		if (just_readed == -1) {
			return -1;
		}
		readed += just_readed;
		printf("Readed: %d/%d\n", just_readed, readed);
	} while ((just_readed > 0) && (readed < sizeof(int)));
	return readed;
}


Ma se lo scambio di int avviene attraverso due macchine con byte
ordering diverso, non serve la conversione con htonl() e ntohl()?
Ne approffitto della tua disponibilità.. Grazie ancora.
Ale

 }
Manlio Perillo

 Manlio Perillo
Grazie per la segnalazione.
Sono d'accordo sul fatto di mettere
just_written = write(sock, p + written, sizeof(int) - written);
e
just_readed = read(sock, p + readed, sizeof(int) - readed);
Il controllo inutile l'ho messo per catturare un eventuale EOF in una
read, forse nella write è inutile, ma nella read lo lascerei.
Per quanto riguarda il byte ordering, cosa ne pensi?
Grazie anche a te, siete gentilissimi.
Ale

 }



Si, se le macchine hanno byte ordering diverso.



Si.. dopo diverse ore di ricerca.. Mi permetto di segnalare questo
link a riguardo:
http://beej.us/guide/bgnet/output/html/multipage/advanced.html#serialization
Che in sostanza tra le altre cose dice che è sempre meglio
"codificare" se si trasmettono numeri.
Speriamo questo post possa tornare utile ad altri..
Grazie ancora del tempo dedicatomi,
Ale

 int sockread(int sock, int *mess) {
se ti passa sotto mano il libro di steven Unix Network Programming 
vedrai come lui wrappi read e write in due funzioni readn e writen (se 
ricordo bene, visto che non ho qui il testo) che prendono in pasto un 
puntatore al buffer e la dimensione da leggere e/o scrivere e chiamano 
la read e la write opportunamente per essere sicuri che tutto sia stato 
letto o scritto.
concettualmente sono come le tue funzioni, solo un po' più snelle. 
Quindi l'idea è buona :-)