View Full Version : [C] dubbio send e recv su programma client-server
Eddie1985
21-12-2011, 11:21
Salve cercherò di spiegare il mio dubbio.
Supponiamo di avere un programma organizzato in due file client.c e server.c .
Nel client sono eseguite più send con lo stesso argomento socket, e tra una send e l'altra vi è altro codice.
Nel server sono invece eseguite lo stesso numero di recv con lo stesso socket della send, e anche qui tra una recv e l'altra vi è altro codice.
La domanda è questa: la "sincronizzazione" tra le varie send e recv è automatica? nel senso, sono sicuro che la seconda send del client si "sposerà" con la seconda recv del server? dopo una send il programma prosegue con l'esecuzione del codice? dopo la recv? vi possono essere dei malfunzionamenti dovuti al fatto, per esempio, che ci sia troppo codice (e quindi il programma "perda troppo tempo") tra una recv e l'altra (nel frattempo il client potrebbe essere andato molto avanti nell'esecuzione del suo codice!)
Grazie
pabloski
21-12-2011, 11:24
tralasciando i dettagli sul fatto che i socket di default sono blocking, c'è da notare che se il client fa send ( o viceversa ) non è detto che il server riceva proprio quel pacchetto
se c'è un altro client "malevolo" che invia pacchetti al server su quella porta? il server potrebbe ricevere questi ultimi
in genere quando fai recv devi in qualche modo creare un loop, dove ricevi i dati, li verifichi e quelli non buoni li scarti
Eddie1985
21-12-2011, 11:27
tralasciando i dettagli sul fatto che i socket di default sono blocking, c'è da notare che se il client fa send ( o viceversa ) non è detto che il server riceva proprio quel pacchetto
se c'è un altro client "malevolo" che invia pacchetti al server su quella porta? il server potrebbe ricevere questi ultimi
in genere quando fai recv devi in qualche modo creare un loop, dove ricevi i dati, li verifichi e quelli non buoni li scarti
mmm potresti farmi un esempio pratico magari scritto in pseudo-codice?
Poi cosa significa che i socket di default sono blocking?
pabloski
21-12-2011, 14:44
mmm potresti farmi un esempio pratico magari scritto in pseudo-codice?
Poi cosa significa che i socket di default sono blocking?
blocking significa che, ad esempio, quando chiami la recv, il programma si blocca finchè la recv non ritorna e la recv ritorna solo quando avrà catturato un blocco di dati
però il problema è che quel blocco di dati può essere stato mandato da qualcuno che non è il client previsto, ma magari un altro client, un programma disturbatore o qualsiasi altro soggetto in grado di mandare dati sulla rete
Eddie1985
21-12-2011, 14:50
blocking significa che, ad esempio, quando chiami la recv, il programma si blocca finchè la recv non ritorna e la recv ritorna solo quando avrà catturato un blocco di dati
però il problema è che quel blocco di dati può essere stato mandato da qualcuno che non è il client previsto, ma magari un altro client, un programma disturbatore o qualsiasi altro soggetto in grado di mandare dati sulla rete
vabbè ma per un programma a scopo didattico non ho di questi problemi giusto?
e cmq la recv è blocking sempre e comunque, oppure solo se vi mettiamo l'opzione WAITALL?
e poi il discorso nn mi torna molto...se la recv è nel server.c sarà questo programma che si blocca, ma il client continuerà a girare no?
pabloski
21-12-2011, 16:26
vabbè ma per un programma a scopo didattico non ho di questi problemi giusto?
dipende dal programma ovviamente :D
anni fa ho scritto un client e un server pxe e lì è normale avere client che interagiscono nello stesso momento con lo stesso server, il tutto in modalità connectionless
per i socket connection oriented, il sistema gestisce la cosa automaticamente
per esempio un normale server telnet non deve fare verifiche, un server dhcp deve eccome
mi era venuto il dubbio perchè usi recv e send, in genere per i socket "normali", cioè quelli connection oriented, si usano read e write
e cmq la recv è blocking sempre e comunque, oppure solo se vi mettiamo l'opzione WAITALL?
no, MSG_WAITALL dice solo che deve aspettare finchè non avrà ottenuto il numero di bytes previsto
normalmente la recv si blocca
e poi il discorso nn mi torna molto...se la recv è nel server.c sarà questo programma che si blocca, ma il client continuerà a girare no?
se il client non ha nessuna recv ovviamente non si bloccherà
la send manda i dati e basta e, a parte problemi nell'invio, viene eseguita velocissimamente
La domanda è questa: la "sincronizzazione" tra le varie send e recv è automatica?
In generale no. bisogna pero' vedere di che socket si tratta. TCP ? UDP ? Unix ? Un pacchetto UDP ad esempio viene in generale spedito "tale e quale" per cui ad ogni pacchetto spedito corrisponde un pacchetto ricevuto. A parte quando viene perso ^_^. Col TCP invece viene garantito che non perdi niente, ma non e' detto che ci sia corrispondeza tra send e recv.
In sostanza: non farci affatto affidamento. Se devi sapere se quante recv devi effettuare, conta il numero di byte che ricevi e continua ad aspettare finche' hai tutti quelli che ti servono.
nel senso, sono sicuro che la seconda send del client si "sposerà" con la seconda recv del server?
no. vedi sopra.
dopo una send il programma prosegue con l'esecuzione del codice? dopo la recv?
La domanda e' mal posta... messa cosi' e' come chiedere "il programma continua o si pianta ? :D
Se intendi se il programma si ferma in attesa che l'altro capo faccia una recv, allora la risposta e' no, usualmente, si tratta solo di aspettare che i dati raggiungano il buffer di spedizione. Con qualche caveat, vedi sotto.
vi possono essere dei malfunzionamenti dovuti al fatto, per esempio, che ci sia troppo codice (e quindi il programma "perda troppo tempo") tra una recv e l'altra (nel frattempo il client potrebbe essere andato molto avanti nell'esecuzione del suo codice!)
Ni, dipende da che protocollo usi.
In un protocollo connectionless tipo UDP se il client continua a spedire e il server non fa le recv, ad un certo punto riempi il buffer disponibili lato server.Da qui in poi i pacchetti successivi verranno persi, finche' non verranno fatte un po' di recv per liberare spazio.
Nel caso TCP e simili invece, una volta che il server ha finito il buffer comunica al client la cosa (e' un po' piu' complesso, ma rende l'idea). A questo punto lato client comincera' a riempirsi il buffer di spedizione. Una volta che si e' riempito del tutto, chiamate a send si bloccheranno e il programma continuera' solo quando il buffer si svuota un po'. A meno che tu non abbia impostato il socket in modalita' non bloccante, in tal caso la send invece che bloccarsi ritorna subito con un particolare codice di errore.
Eddie1985
22-12-2011, 18:59
In generale no. bisogna pero' vedere di che socket si tratta. TCP ? UDP ? Unix ? Un pacchetto UDP ad esempio viene in generale spedito "tale e quale" per cui ad ogni pacchetto spedito corrisponde un pacchetto ricevuto. A parte quando viene perso ^_^. Col TCP invece viene garantito che non perdi niente, ma non e' detto che ci sia corrispondeza tra send e recv.
In sostanza: non farci affatto affidamento. Se devi sapere se quante recv devi effettuare, conta il numero di byte che ricevi e continua ad aspettare finche' hai tutti quelli che ti servono.
no. vedi sopra.
La domanda e' mal posta... messa cosi' e' come chiedere "il programma continua o si pianta ? :D
Se intendi se il programma si ferma in attesa che l'altro capo faccia una recv, allora la risposta e' no, usualmente, si tratta solo di aspettare che i dati raggiungano il buffer di spedizione. Con qualche caveat, vedi sotto.
Ni, dipende da che protocollo usi.
In un protocollo connectionless tipo UDP se il client continua a spedire e il server non fa le recv, ad un certo punto riempi il buffer disponibili lato server.Da qui in poi i pacchetti successivi verranno persi, finche' non verranno fatte un po' di recv per liberare spazio.
Nel caso TCP e simili invece, una volta che il server ha finito il buffer comunica al client la cosa (e' un po' piu' complesso, ma rende l'idea). A questo punto lato client comincera' a riempirsi il buffer di spedizione. Una volta che si e' riempito del tutto, chiamate a send si bloccheranno e il programma continuera' solo quando il buffer si svuota un po'. A meno che tu non abbia impostato il socket in modalita' non bloccante, in tal caso la send invece che bloccarsi ritorna subito con un particolare codice di errore.
dunque sto cominciando a capirci qualcosa.
Allora specifico intanto che utilizzo il protocollo TCP, e quando creo il socket gli passo come secondo parametro (parametro int type) SOCK_STREAM.
Vediamo se riesco adesso a mettere in pratica quanto hai scritto, magari aiutami :D
In pratica nella mia applicazione ho un file client.c, e quando lo eseguo devo immettere un comando, supponiamo send [nome_file] .
Questo determinato comando deve prelevare il file nome_file e spedirlo al server, il quale lo salverà in una sua cartella locale.
Ora io avevo pensato di fare così: quando nel client viene riconosciuto questo comando, invio al server una lettera (che fungerà diciamo da codice), facciamo il carattere S.
Quindi nel client ad un certo punto scriverò una cosa del genere:
char cod_comando = 'S';
send (sd, (void*)&cod_comando, 1, 0);
Ora nel server metterei ad un certo punto una cosa del genere:
recv(sock_des, &comando, 1, MSG_WAITALL);
Dunque in questo penso basti così, visto che si tratta del trasferimento di un solo byte, vero? E' corretto secondo voi fare così?
Quindi proseguendo metto (nel server) subito dopo la recv uno swith (comando), pertanto cosideriamo il caso case 'S'.
Dunque ritornando al client, subito dopo la send metterei una cosa del genere:
int len = strlen (nome_file);
send(sd, (char*)&len, sizeof(len), 0);
send(sd, (char*)nome_file, strlen(nome_file), 0);
send(sd, (char*)&info.st_size, 8, 0); //dico al server quanto è grosso il file che sto per inviare, assumendo che st_size di tipo off_t sia lungo 8 byte
Ma tra una send e l'altra appunto cosa devo mettere affinchè avvenga una corretta sincronizzazione con le recv del server?
Nel server infatti nel case 'S' mettevo qualcosa del genere:
char send_temp[1024];
int lunghezza_nome;
long lunghezza_file;
recv(sock_des, (char*) &lunghezza_nome, 4, 0);
recv(sock_des, send_temp, lunghezza_nome, 0);
recv(sock_des, (char*) &lunghezza_file, 8, 0); //st_size è un long da 8 byte
Qualcuno può intanto chiarirmi come fare?
Grazie
starfred
22-12-2011, 23:37
ok, così di sicuro NON funzionerà mai se hai intenzione di avere più client.
Non funziona per il semplice fatto che, se hai più client, essi vanno a scrivere sulle stesse variabili del server.
Devi utilizzare i semafori.
ok, così di sicuro NON funzionerà mai se hai intenzione di avere più client.
Non funziona per il semplice fatto che, se hai più client, essi vanno a scrivere sulle stesse variabili del server.
Devi utilizzare i semafori.
Non sono d'accordo, secondo me concettualmente può funzionare (apparte qualche svista nel codice ovvio). Se anche dovesse gestire tanti client, cosa che richiederebbe il multi-threading, nessuno interferisce con nessuno (se è questo il problema, come mi sembra di capire) perchè le socket TCP sono identificate da una quaterna di valori: porta sorgente, porta destinazione, ip sorgente, ip destinazione e quindi in una connessione le due "estremità" sono univocamente determinate una volta stabilita la connessione. Se nel client fai N send e nel server fai N recv secondo me non c'è dubbio che lo scambio dati sarà "sincronizzato". L'importante è che il server sappia che il primo dato è il tipo di comando, il secondo la lunghezza del file e via dicendo... Tutto il resto (multiplexing/demultiplexing delle connessioni) ci pensa il kernel... Non so se ho proprio centrato il bersaglio :)
Eddie1985
23-12-2011, 00:52
Non sono d'accordo, secondo me concettualmente può funzionare (apparte qualche svista nel codice ovvio). Se anche dovesse gestire tanti client, cosa che richiederebbe il multi-threading, nessuno interferisce con nessuno (se è questo il problema, come mi sembra di capire) perchè le socket TCP sono identificate da una quaterna di valori: porta sorgente, porta destinazione, ip sorgente, ip destinazione e quindi in una connessione le due "estremità" sono univocamente determinate una volta stabilita la connessione. Se nel client fai N send e nel server fai N recv secondo me non c'è dubbio che lo scambio dati sarà "sincronizzato". L'importante è che il server sappia che il primo dato è il tipo di comando, il secondo la lunghezza del file e via dicendo... Tutto il resto (multiplexing/demultiplexing delle connessioni) ci pensa il kernel... Non so se ho proprio centrato il bersaglio :)
beh si in effetti mi sembra che hai centrato il bersaglio...però da quanto mi spiegavano sopra il discorso mi sembrava diverso....
Ma tra una send e l'altra appunto cosa devo mettere affinchè avvenga una corretta sincronizzazione con le recv del server?
Nel server infatti nel case 'S' mettevo qualcosa del genere:
char send_temp[1024];
int lunghezza_nome;
long lunghezza_file;
recv(sock_des, (char*) &lunghezza_nome, 4, 0);
recv(sock_des, send_temp, lunghezza_nome, 0);
recv(sock_des, (char*) &lunghezza_file, 8, 0); //st_size è un long da 8 byte
Qualcuno può intanto chiarirmi come fare?
Grazie
La strada mi sembra abbastanza giusta.
La sincronizzazione la fai sui byte inviati. Tanti ne invii tanti ne devi ricevere. Ovviamente devi sapere lato server quanti byte devi ricevere.
Per sapere questo puoi decidere di usare messaggi sempre della stessa dimensione, oppure di spedire per prima cosa la dimensione totale dei byte da leggere, oppure designare un carattere particolare come fine del messaggio.
Spedire la dimensione del messaggio (o delle sue parti) e' secondo me la cosa piu' semplice da implementare.
E' simile all'approccio che stai usando.
- Invii il comando (1 char fisso)
- Invii la dimensione della stringa col nome del file, oppure la stringa terminata da '\0'. Dall'altro lato leggi la stringa
- Leggi ed invii la dimensione N in byte del file. La invii al server.
- Leggi da disco e scrivi su socket N byte, che leggi dall'altra parte.
Come vedi alla fine dell'operazione sono sincronizzato. Tanti byte ho scritto, tanti ho letto. Fine.
Non sono d'accordo, secondo me concettualmente può funzionare (apparte qualche svista nel codice ovvio). Se anche dovesse gestire tanti client, cosa che richiederebbe il multi-threading, nessuno interferisce con nessuno (se è questo il problema, come mi sembra di capire) perchè le socket TCP sono identificate da una quaterna di valori: porta sorgente, porta destinazione, ip sorgente, ip destinazione e quindi in una connessione le due "estremità" sono univocamente determinate una volta stabilita la connessione. Se nel client fai N send e nel server fai N recv secondo me non c'è dubbio che lo scambio dati sarà "sincronizzato". L'importante è che il server sappia che il primo dato è il tipo di comando, il secondo la lunghezza del file e via dicendo... Tutto il resto (multiplexing/demultiplexing delle connessioni) ci pensa il kernel... Non so se ho proprio centrato il bersaglio :)
No non funziona...
Intanto lasciamo da parte il discorso di piu' client... questo lo risolvi a monte ed e' un problema ortogonale a quello in questione. Qui parliamo di una connessione su uno stream socket TCP. Per cui la connessione e' gia' stata effettuata, l'eventuale thread gia' avviato e non ci sono dubbi che i byte che il client manda arrivino a chi di dovere.
Questo non toglie pero' che il numero di send e recv non e' necessariamente uguale. Quando hai un socket come TCP non c'e' alcun concetto di pacchetti, pezzi di byte distinti dagli altri etc. C'e' solo un flusso piu' o meno costante di byte. Quello che ottieni con la recv non e' altro che il contenuto del buffer di sistema. In condizioni ottimali (cioe' la recv e' li in attesa di dati e il sistema e' scarico) appena una send manda dei dati, questi mi arrivano nel buffer e mi vengono restituiti dalla recv. Ma se il sistema e' intasato ? Puo' succedere che ricevo due, tre o piu' pacchetti di fila e che questi si accumulino nel buffer. Quando finalmente avro' il tempo di leggere il socket, la recv probabilmente mi restituira tutti e tre i pacchetti contemporaneamente (sempre nell'ipotesi che cerco di leggere tutto in un colpo eh). Ottengo tre send e una recv.
Ma se il sistema e' intasato ? Puo' succedere che ricevo due, tre o piu' pacchetti di fila e che questi si accumulino nel buffer. Quando finalmente avro' il tempo di leggere il socket, la recv probabilmente mi restituira tutti e tre i pacchetti contemporaneamente (sempre nell'ipotesi che cerco di leggere tutto in un colpo eh). Ottengo tre send e una recv.
La recv restituisce il numero di byte specificato come parametro quindi tu puoi ricevere tutto quello che vuoi ma è l'applicazione che decide quanti dati prelevare dal buffer e man mano che li legge capisce come interpretare i successivi (sulla base del protocollo applicativo previsto dall'utente che deve gestire i vari casi ovviamente). Perchè mai dovresti leggere tutto in un colpo? Difatti marco.r i campi li legge uno alla volta quando disponibili quindi deve solo mettere d'accordo client e server sul protocollo da usare (che poi è lo scopo dell'esercizio credo) :)
Eddie1985
23-12-2011, 10:50
mmm dunque purtroppo continuo ad essere confuso :D .
Cerchiamo di fare chiarezza!
Qui parliamo di una connessione su uno stream socket TCP. Per cui la connessione e' gia' stata effettuata, l'eventuale thread gia' avviato e non ci sono dubbi che i byte che il client manda arrivino a chi di dovere.
E' esattamente come hai scritto!
E' simile all'approccio che stai usando.
- Invii il comando (1 char fisso)
- Invii la dimensione della stringa col nome del file, oppure la stringa terminata da '\0'. Dall'altro lato leggi la stringa
- Leggi ed invii la dimensione N in byte del file. La invii al server.
- Leggi da disco e scrivi su socket N byte, che leggi dall'altra parte.
Come vedi alla fine dell'operazione sono sincronizzato. Tanti byte ho scritto, tanti ho letto. Fine.
Non è esattamente quello che ho fatto io? :confused:
Ma io continuo a non capire se le problematiche che cercavo di spiegare all'inizio del thread ci siano oppure no! :muro:
Dunque dopo che ho fatto le send dal lato client, i dati saranno o nelle variabili o comunque in un buffer, e prima o poi verranno presi dalla recv del lato server? Ma intanto il lato client, dopo aver eseguito le send, va avanti con il codice, e chi mi garantisce che le recv sul lato server siano già state effettuate????
Si ma qui i problemi sono due:
1) Sincronizzazione tra server e client, cioè quello che uno invia l'altro lo legge. E abbiamo detto di si, se gestisci opportunamente il flusso e la sequenza di "campi" che invii dall'altra parte si, puoi fare in modo che client e server siano sempre sincronizzati (dipende solo da te e secondo me stavi facendo bene).
2) Il client invia un dato e vuole accertarsi, prima di proseguire, che il server l'abbia ricevuto. Questo è un altro problema. Se vuoi essere sicuro della ricezione dovresti prevedere ACK espliciti che, secondo me, non servono a niente nel tuo caso: il client prosegue l'esecuzione, prima o poi aspetterà risposte dal server e si metterà in ricezione con la recv fino a quando il server risponde. Se l'applicazione è fatta bene queste risposte arriveranno, devi prevedere che client e server non siano mai ENTRAMBI in recv() altrimenti ottieni un deadlock...
Eddie1985
23-12-2011, 11:15
Si ma qui i problemi sono due:
2) Il client invia un dato e vuole accertarsi, prima di proseguire, che il server l'abbia ricevuto. Questo è un altro problema. Se vuoi essere sicuro della ricezione dovresti prevedere ACK espliciti che, secondo me, non servono a niente nel tuo caso: il client prosegue l'esecuzione, prima o poi aspetterà risposte dal server e si metterà in ricezione con la recv fino a quando il server risponde. Se l'applicazione è fatta bene queste risposte arriveranno, devi prevedere che client e server non siano mai ENTRAMBI in recv() altrimenti ottieni un deadlock...
Si il problema direi che è questo!
Mi rimetto a lavoro così in caso vi richiedo aiuto :mc:
starfred
23-12-2011, 11:54
Attenzione a non confondere il descrittore di socket, diverso per ogni connessione, con il fatto che le recv vanno a scrivere sulle stesse variabili del server.
Per quel che riguarda la consistenza dei dati, essa è implicita nel protocollo TCP. E' raro dover implementare un controllo con degli ACK se non in alcuni casi particolari. Per esempio l'invio di un grosso buffer con parecchie send.
Eddie1985
23-12-2011, 12:37
Attenzione a non confondere il descrittore di socket, diverso per ogni connessione, con il fatto che le recv vanno a scrivere sulle stesse variabili del server.
non ho capito :(
Per quel che riguarda la consistenza dei dati, essa è implicita nel protocollo TCP. E' raro dover implementare un controllo con degli ACK se non in alcuni casi particolari. Per esempio l'invio di un grosso buffer con parecchie send.
Il fatto di usare o meno parecchie send per l'invio di un file immagino dipenderà anche da "quanto" invio con ogni send. Cioè se invio un byte alla volta anche per un file piccolo avrò bisogno di molte send, se invio un kb alla volta ovviamente ce ne vorranno molte meno. Cosa mi consigliate? Quale è la dimensione opportuna da inviare secondo voi?
starfred
23-12-2011, 13:05
Io immagino che tu stia in un sistema multithread, nel quale ogni thread gestisce un socket descriptor, cioè che ogni thread gestisce una connessione con un client. Se qualche thread fa riferimento a variabili globali, come nel 99% dei casi avviene, allora devi implementare un meccanismo di mutua esclusione per tali variabili.
Spero di esser stato chiaro.
Ciao
Cosa mi consigliate? Quale è la dimensione opportuna da inviare secondo voi?
Discorso lungo...
Ogni send (almeno in linea di principio) diventa un pacchetto del flusso TCP o, nel caso la quantità di dati sia troppo grande per un singolo pacchetto, viene frammentata in N pacchetti che poi il ricevitore ricompone. Per massimizzare l'efficienza dovresti fare pacchetti più grande possibile in modo da minimizzare il numero di pacchetti e, di conseguenza, l'overhead dovuto agli header TCP, IP, ecc che devi aggiungere ad ogni pacchetto. D'altro canto, se fai pacchetti grandi, se se ne perde uno e TCP deve ritrasmetterlo, ritrasmetterà una quantità di dati maggiore. Insomma, è un compromesso: per grosse quantità di dati, io farei pacchetti grossi (non meno di 512-1024 byte alla volta) :)
Io immagino che tu stia in un sistema multithread, nel quale ogni thread gestisce un socket descriptor, cioè che ogni thread gestisce una connessione con un client. Se qualche thread fa riferimento a variabili globali, come nel 99% dei casi avviene, allora devi implementare un meccanismo di mutua esclusione per tali variabili.
Spero di esser stato chiaro.
Ciao
Nel tuo esempio si bisogna stare attenti, ma è appunto un esempio di server scritto non proprio bene. Ogni thread può tranquillamente mallocarsi il suo buffer di ricezione senza rompere le scatole agli altri con variabili globali. L'onere di gestire dei semafori è abbastanza grande mentre di RAM ormai ce n'è a bizzeffe :)
Non è esattamente quello che ho fatto io? :confused:
Ma io continuo a non capire se le problematiche che cercavo di spiegare all'inizio del thread ci siano oppure no! :muro:
Dunque dopo che ho fatto le send dal lato client, i dati saranno o nelle variabili o comunque in un buffer, e prima o poi verranno presi dalla recv del lato server? Ma intanto il lato client, dopo aver eseguito le send, va avanti con il codice, e chi mi garantisce che le recv sul lato server siano già state effettuate????
Ok, ora ho capito meglio.
Tu non sai se e quando il server abbia fatto delle recv. Se la tua send ritorna con successo sai che in linea di massima i dati sono arrivati all'altro capo, ma potrebbero essere fermi in qualche buffer. Se vuoi avere qualche garanzia (tipo che il server ha finito di salvare i dati su disco) devi far si che il server risponda con qualche comando di conferma.
Di cosa vuoi aver conferma ?
Eddie1985
23-12-2011, 16:46
o immagino che tu stia in un sistema multithread, nel quale ogni thread gestisce un socket descriptor, cioè che ogni thread gestisce una connessione con un client. Se qualche thread fa riferimento a variabili globali, come nel 99% dei casi avviene, allora devi implementare un meccanismo di mutua esclusione per tali variabili.
mmm non mi pare di usare variabili globali nel mio caso...
Discorso lungo...
Ogni send (almeno in linea di principio) diventa un pacchetto del flusso TCP o, nel caso la quantità di dati sia troppo grande per un singolo pacchetto, viene frammentata in N pacchetti che poi il ricevitore ricompone. Per massimizzare l'efficienza dovresti fare pacchetti più grande possibile in modo da minimizzare il numero di pacchetti e, di conseguenza, l'overhead dovuto agli header TCP, IP, ecc che devi aggiungere ad ogni pacchetto. D'altro canto, se fai pacchetti grandi, se se ne perde uno e TCP deve ritrasmetterlo, ritrasmetterà una quantità di dati maggiore. Insomma, è un compromesso: per grosse quantità di dati, io farei pacchetti grossi (non meno di 512-1024 byte alla volta)
con grosse quantità di dati intedi roba dell'ordine di?
Ok, ora ho capito meglio.
Tu non sai se e quando il server abbia fatto delle recv. Se la tua send ritorna con successo sai che in linea di massima i dati sono arrivati all'altro capo, ma potrebbero essere fermi in qualche buffer. Se vuoi avere qualche garanzia (tipo che il server ha finito di salvare i dati su disco) devi far si che il server risponda con qualche comando di conferma.
Di cosa vuoi aver conferma ?
Beh se spedisco il file, vorrei avere la conferma che esso sia stato ricevuto. Se spedisco il nome del file, vorrei la conferma che esso sia stato ricevuto. E così via.
Ma a quanto mi hanno detto queste conferme non sono necessarie.
O sbaglio? :confused:
Beh se spedisco il file, vorrei avere la conferma che esso sia stato ricevuto. Se spedisco il nome del file, vorrei la conferma che esso sia stato ricevuto. E così via.
Ma a quanto mi hanno detto queste conferme non sono necessarie.
O sbaglio? :confused:
Allora la conferma non serve per quel che riguarda la trasmissione in se'. Immagino pero' ti servira almeno una conferma che tutta la transazione e' andata a buon fine (e se finisce il disco? Se non puoi creare il file ? Se c'e' qualcosa che non va nei dati che hai spedito ?)
con grosse quantità di dati intedi roba dell'ordine di?
Difficile dare un numero preciso, dipende dal contesto. Se ti interessano le prestazioni potresti voler ottimizzare anche l'invio di 1000 byte così come di 10 MB, non è che ci sia un numero preciso, sono scelte di progetto...
Per quanto riguarda le conferme NO, non sono necessarie nel senso che i dati arrivano sicuramente. Però, come giustamente facevano notare, il fatto che i dati arrivino non significa che tutto andrà bene: disco pieno, ram finita, ecc... Per risolvere questo problema ci vuole qualcosa di più complesso, tipo una connessione di controllo separata (come il protocollo FTP) per segnalare eventuali problemi da server a client e viceversa. Però in questo caso ti servono più thread... Non mi viene in mente niente di semplicissimo da implementare, pensaci su! :)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.