Newsgroup: it.comp.os.linux.development
Titolo: socket read write e lunghezza dati variabile

Salve stò realizzando un applicazione client/server in C e ho un
piccolo problema x la lettura/scrittura dei dati su un socket...Da
quanto ho capito devo iterare la read e la write finchè non ho letto/
scritto la quantità richiesta di dati in quanto possono essere sospese
da segnali tipo EINTR facendo qualcosa del genere (nn l'ho scritto
io :) )
ssize_t writen(int fd, const void *buf, size_t n)
{
  size_t nleft;
  ssize_t nwritten;
  const char *ptr;
  ptr = buf;
  nleft = n;
  while (nleft > 0) {
    if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
       if ((nwritten < 0) && (errno == EINTR)) nwritten = 0;
       else return(-1);         /* errore */
   }
    nleft -= nwritten;
    ptr += nwritten;
  } /* end while */
  return(nleft);
}
ora come faccio a far sapere alla read la lunghezza dei dati da
leggere quando questa può variare e di molto???


Prima mandi la lunghezza, e poi i dati. Cosi' la read sa quanto leggere.
-- 
Salvatore Iovene
http://www.iovene.com/

 Prima mandi la lunghezza, e poi i dati. Cosi' la read sa quanto leggere.
oppure usi dei datta strutturati. O dei marker di sincronzzazione.
Perň mandare la lunghezza puň essere piů efficiente.

 Però mandare la lunghezza può essere più efficiente.
grazie a  tutti...perciò basterebbe  prima spedire la lunghezza
ricevere risposta di avvenuta ricezione e poi spedire il messaggio
completo?
marker di sincronizzazione??cosa sarebbero?

 completo?
No. Supponiamo che tu voglia mandare delle stringhe, ed ad un certo
punto vuoi mandare "Hello world\0", che sono 12 bytes.
Supponiamo inoltre che la lunghezza massima che puoi mai voler mandare
sia 1024 bytes, che e' quindi un numero espribimile con 10 bits. Ti
servono quindi 2 bytes per rappresentare il numero in notazione binaria.
Oppure puoi rappresentarlo in notazione esadecimale e risparmi qualcosa
in piu'.
12 in esadecimale e' 0C, quindi quello che in realta' mandi sul socket
e': "0CHello world\0".
Nel processo hce legge invece farai cosi':
prima leggi 2 bytes, ti ricalcoli 0C in decimale e quindi sai che devi
leggere altri 12 bytes. Cosi' NELLO STESSO CICLO puoi fare una seconda
read, stavolta di 12 bytes. Ed il gioco e' fatto.
Questo ti garantisce anche che, in caso l'altro processo spedisca
velocemente due pacchetti (pacchetto inteso secondo il tuo personale
protocollo di comunicazione), tu saprai spezzarli.
Spero sia stato chiaro!


 
Puoi provare questo:
int readSocket(int fd, char *readbuffer)
{
   char buffer[BUFFSIZE];
   int rc, readlen = 0;
   while ((rc = read(fd, buffer, sizeof(buffer))) > 0) {
	memcpy(readbuffer, buffer, rc);
	readbuffer += rc;
	readlen += rc;
   }
   return readlen;
}
Ma dipende dal protocollo.  La read, se il socket e` correttamente 
inizializzato e se non ci sono dati da leggere, ritorna 0;
Il buffer dove si travasano i dati (readbuffer) deve essere abbastanza 
grande da contenere rutti i dati, altrimenti si devono prevedere 
meccanismi di riallocazione.
Ciao
Giovanni
-- 
   A computer is like an air conditioner,
   it stops working when you open Windows.
   Registered Linux user #337974  < 
http://giovanni.homelinux.net/
 >

usa la select
arbiter ha scritto:


 Spero sia stato chiaro!
mmm si credo di aver capito basta grazie mille!

 marker di sincronizzazione??cosa sarebbero?
ti faccio un esempio dal mondo reale: jpeg prevede dei byte particolari
all'interno del bitstream in modo che il decoder possa muoversi
facilmente in esso e che le applicazioni sappiano trovare i dati.
Una immagine jpeg inizia con il numero 0xFFD8 e termina con0xFFD9.
Quindi, per esempio, se vuoi scaricare questo dato basta che leggi byte
a byte fino a quando non leggi prima 0xFF e poi 0xD9. :-)

 Salvatore Iovenehttp://
www.iovene.com/
Siete stati tutti chiarissimi grazie mille! ora mi metto sotto con
l'implementazione :)