PDA

View Full Version : problema C socket


marcus81
22-09-2005, 22:45
salve ragazzi!
Ho un problemino con una applicazione client-server in C.
In pratica, facendo girare client e server sullo stesso PC non ho nessun problema e tutto gira alla perfezione; se lancio invece client e server su 2 pc della mia lan ho dei problemi con i comandi, nel senso che i comandi è come se arrivassero in ritardo e non sincronizzati al server.
Si tratta di 2 semplici giochini che funzionano sul server.
Sono stati compilati sotto linux ovviamente.
Se potete farmi il favore di darci un occhiata...e dirmi cosa potrebbe essere che non va...scusate per il codice C.Grazie.
li allego

marcus81
23-09-2005, 12:50
Nessuno ci ha capito niente?
Potreste almeno farmi il favore di provarli su 2 PC?
Non capisco perchè su un singolo PC tutto funziona alla perfezione, ma su 2 spuntano problemi di sincronizzazione client-server.
Grazie :)

ilsensine
23-09-2005, 12:56
E' un errore frequente.

La recv ritorna i byte nel buffer di ricezione, fino al massimo che tu indichi. La rete è libera di spezzettare i pacchetti come vuole. In locale la mtu è molto grande (16kb), quindi non osservi il problema. Ma la mtu ethernet è circa 1500, questo vuol dire che i pacchetti di 4kb vengono sicuramente frammentati e quello che ti accade è che stai leggendo il primo pacchetto mentre il secondo è ancora in ricezione.
Puoi sincerarti di questo controllando il valore ritornato dalla recv (che è il numero di byte effettivamente letti) e puoi verificare come risulta <4096 quando noti il disallineamento.

marcus81
23-09-2005, 13:10
Ho capito perfettamente la tua risposta, anche perchè sto studiando reti e ho appena fatto la frammentazione dei datagram su ethernet :)
Ma non ci dovrebbe essere dopo la frammentazione un riassemblaggio all'host?
Sei un grande!

Adesso mi chiedo: c'è un modo per risolvere il fastidioso problema?dovrei per forza di cose ridurre il buffer? o c'è un altra soluzione?
Grazie ancora ;)

marcus81
23-09-2005, 13:29
Ho provato a visualizzare il valore ritornato dalla recv e mi restituisce sempre 0 :confused:

marcus81
23-09-2005, 13:48
ho diminuito il buffer a 1400 è tutto sembra funzionare :)
Spero di non avere altri problemi!
Grazie mille ;)

PS: ma non c'è un'altra soluzione per risolvere il problema?

ilsensine
23-09-2005, 15:05
Ma non ci dovrebbe essere dopo la frammentazione un riassemblaggio all'host?

Non esiste il "pacchetto tcp" ad alto livello. Il tcp è un protocollo "stream", quello che arriva può essere letto immediatamente. Se leggi un pacchetto prima che arrivino i successivi, hai solo i dati di un pacchetto.

L'udp funziona in maniera differente, tantè che mentre puoi leggere un byte alla volta su uno stream tcp senza perdere nessun dato, se leggi solo un byte da un socket udp il resto dei dati del datagramma viene buttato!

ilsensine
23-09-2005, 15:11
ho diminuito il buffer a 1400 è tutto sembra funzionare :)
Spero di non avere altri problemi!
E' sbagliato fare assunzioni sulla mtu, sia concettualmente che praticamente (se i due computer sono connessi tramite ad es. un modem gsm o altro canale del quale sai poco? Se il vostro sysadmin vuole impostare un mtu minore sulle schede ethernet?)

PS: ma non c'è un'altra soluzione per risolvere il problema?
Se sai esattamente quanto leggere, ripeti la lettura finché non leggi tutto. Qualcosa del genere insomma:

int recv_block(int fd, char *buf, int sz) {
while (sz>0) {
int dim = recv(fd, buf, sz, MSG_NOSIGNAL);
if(!dim) break; /* EOF=disconnessione del peer */
else if(dim==-1) {
if(errno==EINTR) continue; /* il programma ha ricevuto un segnale */
break;
}
buf += dim;
sz -= dim;
}
return sz==0 ? 0 : -1;
}

marcus81
23-09-2005, 19:10
Ma se provo a visualizzare il valore ritornato da recv come mai è sempre zero?
Non so esattamente quanto leggere perchè di volta in volta passo delle stringhe di lunghezza sempre diversa,altrimenti dovrei imporre un massimo di lettura?
non sarebbe sempre limitativo?

edit: ho appena visto che in C la funzione recv ritorna 0 oppure -1 in caso di errore.

ilsensine
26-09-2005, 11:44
Ma se provo a visualizzare il valore ritornato da recv come mai è sempre zero?
Il tuo PC è posseduto oppure stai sbagliando qualcosa di ovvio.

Non so esattamente quanto leggere perchè di volta in volta passo delle stringhe di lunghezza sempre diversa
Supponi che le stringhe da leggere sinano concatenate dentro un file, e devi leggerle da lì. Non sai la dimensione delle stringhe. Come faresti?
Hai varie soluzioni; dal prependere alla stringa la sua dimensione, al leggere un byte alla volta finché non incontri '\0', al riempire un certo buffer e rintracciare lì dentro con calma le stringhe complete. Inventati qualcosa, la soluzione non è unica.

edit: ho appena visto che in C la funzione recv ritorna 0 oppure -1 in caso di errore.
"0" non è veramente un errore; interpretalo come EOF.