PDA

Visualizza la versione completa : [C++] Invio vettore di grandi dimensioni tramite socket


alfa_19
16-09-2011, 11:15
Salve a tutti.

Io mi ritrovo ad avere un vettore di char molto grosso, diciamo anche oltre il milione di elementi.

Quello che voglio fare è inviare l'intero contenuto del vettore tramite socket ad un'applicazione client.

quello che faccio è suddividere il vettore in mini-vettori da 8192 caratteri, e poi fare una send per ogni blocco.


long int totale = 0;
char vettore_grande[1000000];
char vettore_mini[8192];
int i;

while(totale<1000000){
for(i=0;i<8192;i++){
vettore_mini[i] = vettore_grande[totale];
totale++;
}
send(s,vettore_mini,8192,0);
}

lasciate perdere il fatto che l'ultimo pacchetto potrebbe non essere un multiplo di 8192, ho già fatto il controllo solo non lo riporto per non appesantire qua.

L'invio funziona anche benissimo perchè effettivamente facendo un conteggio dei byte inviati alla fine ottengo esattamente 1000000.

Il problema è alla ricezione:


char vettore_mini[8192];
int conta;

case FD_READ:

conta = recv(s,vettore_mini,8192,0);

tralascio la parte di codice in cui man mano ricopio il contenuto di vettore mini all'interno di un vettore più grande (inverso del caso sopra). Quello che importa è che contando il numero di byte totali ricevuti (sommando in una variabile globale dopo ogni recv il valore di conta) non arrivo mai ad 1000000; a volte si ferma a 750000 circa, a volte a 800000 circa ma non riceve mai tutti i byte inviati.

A cosa è dovuto questo? io sulla recv non ho nessuna condizione di terminazione, cioè in pratica per ogni send la recv dovrebbe comunque essere attivata.

Grazie mille per le risposte in anticipo :)

oregon
16-09-2011, 11:21
Non c'è corrispondenza diretta tra il numero di dati inviati e quelli ricevuti.

Ovvero, se invii 8192, non è detto che ne ottieni subito 8192 in ricezione ma ne potresti ottenere 4000, dopo un po' 3000, intanto ne invii altri 8192 e ne ricevi 2000 e così via ... l'unica cosa di cui sei certo è l'ordine di trasmissione/ricezione.

In teoria, potresti inviare con una sola send tutto il milione di char ...

Sul fatto che ne ricevi meno di quelli inviati, non è facile dire il perché se non gestisci gli errori ...

alfa_19
16-09-2011, 11:54
Ok sono un pò ignorante in materia, ma grazie per la tempestiva risposta.

Rispondo a punti:

1. Supponiamo che io invio tutto il milione di char. A questo punto da quanto mi dici tu devo fare più di una recv per riceverlo tutto (anche perchè ho già provato e ne riceveva si e no 11000 con una recv sola). Come faccio? faccio una cosa del genere in fase di ricezione?


int c;
long int contatore_totale;

while(contatore_totale<1000000){
c = recv(s,vettore, 8192,0);
contatore_totale += c;
}

ovviamente salvando in ogni ciclo ciò che ho ricevuto in un vettore più grande.

Oppure come?

2. Gestione degli errori sono pronto a farla, ma non ho la minima idea di come farla....qualche link di spiegazione rapida ce l'hai per caso?

Grazie mille ancora :)

oregon
16-09-2011, 13:07
Sì, devi eseguire più recv fino a che ottieni i dati che avevi inviato.

Se fai una sola recv ti possono arrivare x byte, gli altri li ricevi con un'altra recv *indipendentemente* da quanti sono quelli inviati in un singolo blocco.

La gestione degli errori la fai dando un'occhiata accurata a cosa restituisce la recv.
Come mai usi la recv ? Dove hai studiato come funziona ?

alfa_19
16-09-2011, 13:23
bah perchè per inviare dati tramite socket ho sempre pensato che si usassero send e recv. C'è una soluzione migliore?

Ad ogni modo correggimi se sbaglio: la recv riceve un numero di byte non dipendente direttamente dal numero totale di byte inviati mediante un unica send; però siamo sicuri che il numero di byte ricevuti non eccede mai la dimensione indicata dal terzo parametro.

Quindi se io faccio:


recv (s,vettore,8192,0);

la recv potrà ricevere 180, 2000, 8192 ma non 10500 byte giusto?

facendo più recv però io sono sicuro al 100% che i dati arriveranno comunque tutti e in ordine corretto?

Tornando invece al mio esempio io posso fare una cosa del genere?

Codice Invio Dati

send(s,vettore_grande,1000000,0);

Codice Ricezione Dati

long int conta = 0;
int ric;

while(conta<1000000){
ric = recv(s,(char *)&vettore_grande[conta],1000000,0);
conta += ric;
}

Grazie :)

oregon
16-09-2011, 13:41
Originariamente inviato da alfa_19
bah perchè per inviare dati tramite socket ho sempre pensato che si usassero send e recv. C'è una soluzione migliore?

Il fatto è che l'hai adottata senza averne mai letto la documentazione, dato che non sai come trattare gli errori ... leggi

http://msdn.microsoft.com/en-us/library/ms740121(v=vs.85).aspx



Ad ogni modo correggimi se sbaglio: la recv riceve un numero di byte non dipendente direttamente dal numero totale di byte inviati mediante un unica send; però siamo sicuri che il numero di byte ricevuti non eccede mai la dimensione indicata dal terzo parametro.

Sì, per quella chiamata ..


Quindi se io faccio:


recv (s,vettore,8192,0);

la recv potrà ricevere 180, 2000, 8192 ma non 10500 byte giusto?

Giusto



facendo più recv però io sono sicuro al 100% che i dati arriveranno comunque tutti e in ordine corretto?

Corretto, a meno che non intervengano errori (la comunicazione può sempre saltare) e te ne accorgi da ciò che ti dice la recv (e anche la send ...)



Tornando invece al mio esempio io posso fare una cosa del genere? ...

Quasi ... ti ho già detto ... nel ciclo devi gestire eventuali errori della recv ...

alfa_19
16-09-2011, 13:47
Ok ma supponiamo per adesso che la recv non dia mai errori, il mio codice sarebbe giusto?

oregon
16-09-2011, 13:55
Sì ...

alfa_19
16-09-2011, 13:56
Ok perfetto...sei stato davvero gentilissimo...adesso mi leggo tutta la documentazione per gli errori...se poi non funzionasse mi ritroverai qua :)

alfa_19
16-09-2011, 15:05
Si verifica un errore quanto mai strano del quale sinceramente non riesco a capirne il motivo.

Il codice è quello riportato sopra:


while(conta<1000000){
ric = recv(s,(char *)&vettore_grande[conta],1000000,0);
conta += ric;
}

Debuggando l'interno del while succede che conta arriva effettivamente a valere 1000000 preciso (quindi questo vuol dire che il client ha ricevuto interamente il vettore), peccato che per qualche strana ragione che io non conosco l'applicazione non esce dal while, e al ciclo successivo per qualche motivo sia ric che conta valgono -1. Cioè ric so perchè, la recv ha dato errore in quanto -1 non può essere usato come indice di un vettore.

Ma xk non esce dal ciclo? quando fa il controllo tra conta e 1000000 dovrebbe uscire....

Loading