Newsgroup: it.comp.os.linux.development
Titolo: Problema con send e recv in remoto

Sistema op suse 9.2 compilatore gcc linguaggio C (stesse versioni su entrambi
i 
PC).
Server e client sono connessi tramite socket con protocollo TCP
Un server invia una matrice(statica) al client che la visualizza su schermo.
1 caso) Client e server girano sulla stessa macchina(cmq viene simulta la
connessione xchè si utlizzano i socket). La visualizzazione da parte del
client su 
video avviene senza problemi.
2 caso) Client e Server girano su macchine differenti.(sresso codice dekl
primo 
caso) IL client nn visualizza la matrice (a volte in parte a volte no) e
si blocca.
Di seguito riporto il codice del server che inizializza/crea la matrice.
Non fate caso al puntatore che mi serve x mantenre condiviso un flag(posto
vuoto/libero) che cmq nn viene utilizzato con la send e recv, quindi nn coinvolge
il 
client.
[code]
struct posto
{
  unsigned char idPosto[6]; // i caratteri che indicano fila e posto sono
memo qui
    int *flag;   // flag poso libero/prenotato
};
[/code]
[code]
struct posto cinema [3][3];
void inizializza_cinema(struct posto cine[3][3],int *p)
{
 
 unsigned char i,j,k;
 int *pp,*ppp;
 pp=p;
 ppp=p;
 for(i='A';i<='C';i++)
  {
 
    for(j='1';j<='3';j++)
     {cine[i-'A'][j-'1'].flag=ppp;
      ppp=ppp+1;
     }
   }
 
 k='1';
 for(i='A';i<='C';i++)
  {
 
    for(j='1';j<='3';j++)
     { *pp=0;
       cine[i-'A'][j-'1'].flag=0;
       cine[i-'A'][j-'1'].idPosto[0]=' ';
       cine[i-'A'][j-'1'].idPosto[1]=i;
       cine[i-'A'][j-'1'].idPosto[2]=j;
       cine[i-'A'][j-'1'].idPosto[3]=' ';
       cine[i-'A'][j-'1'].idPosto[4]='\t';
       cine[i-'A'][j-'1'].idPosto[5]='\0';
       pp=pp+1;
     }
     cine[i-'A'][2].idPosto[4]='\n';
   }
 };
[/code]
di seguito il codice del server che spedisce la matrice vettore x vettore
al client.
[code]
 void posti_vuoti(struct posto cine[3][3],int *p)
 { int *pp;
   pp=p;
   unsigned char i,j;
   i='A';
   j='1';
   send(ds_sock_acc,"\n\nI posti contrassegnati con le parentesi quadre sono
già 
assegnati!!\n\n",MAX_DIM,0);
   for (i='A'; i<='C'; i++)
     {
 
       for (j='1'; j<='3'; j++)
         {
	   if (*pp==0)
	   if (cine[i-'A'][j-'1'].flag==0)
	     { cine[i-'A'][j-'1'].idPosto[0]=' ';
	       cine[i-'A'][j-'1'].idPosto[3]=' ';
	       send(ds_sock_acc,&cine[i-'A'][j-'1'].idPosto,MAX_DIM,0);
 
	      }
	   else //posto occupato lo stampo tra le parentesi []
	      { cine[i-'A'][j-'1'].idPosto[0]='[';
	        cine[i-'A'][j-'1'].idPosto[3]=']'; 
 
		send(ds_sock_acc,&cine[i-'A'][j-
'1'].idPosto,MAX_DIM,0);
			       }
	       pp=pp+1;
	  }
       }
 
 
      send (ds_sock_acc,"\nFatto",10,0);
};
[/code]
ora  codice funzione visualizza matrice del client:
[code]
void visualizza()
{ char buf[MAX_DIM];
  do
    {
      recv(ds_sock,&buf,MAX_DIM,0);
      if (strcmp(buf,"Fatto")!=0)
      {
      printf("%s",buf);
      }
    } 
     while (strcmp(buf,"\nFatto")!=0);
  sleep(3);
 
};
[/code]
Quindi il client x primo stampa il messaggio :i posti prenotato si trovano
tra 
parentesi []
il primo vettore della matrice A1 A2 A3 e poi si blocca.
Nel caso di processi su macchina locale come detto i lclient stampa
A1 A2 A3
B1 B2 B3
C1 C2 C3
Quindi il server invia \nFatto  che è la condizione di uscita.
Ripeto in locale(simulata xro' la connessione) va da remoto no :(
Non riesco a capire come mai le send e recv nn funzionino a dovere con la
connessione i nremoto .
Qualcuna spero mi sappia aiutare. C'è un modo x controllare il giusto flusso
di dati 
x garantire la giusta visualizzazione ????????
-----
Msg posted via: 
http://www.TechEye.it
-----
Msg posted via: 
http://www.TechEye.it

    recv(ds_sock,&buf,MAX_DIM,0);
Non va bene. Ogni successiva chiamata a 'recv' sovrascrive il contenuto di 
'buf', mentre tu vorresti in realtà aggiungere i dati in coda, giacché ci 
possono volere più letture per esaurire i dati inviati dal client.  
Max

       recv(ds_sock,&buf,MAX_DIM,0);
E come sai che recv ha ricevuto tutto e non ha dato errori?
I valori di ritorno delle funzioni si controllano *sempre*. Ci possono
essere errori. Inoltre quando usi funzioni di lettura e scrittura su
socket di rete niente ti assicura che i dati vengano inviati sempre
tutti assieme.
Ciao
-- 
As.| Simone Piccardi - KeyID:2A972F9D - 
JabberID:sim...@jabber.linux.it
So.| 
http://firenze.linux.it/~piccardi
  -  
http://www.softwarelibero.it
Li.| Prima ti ignorano, poi ti deridono, poi ti combattono.  Poi vinci.
                                                           M. K. Ghandi

Vi ringrazio per aver risposto, xro' nn ho capito come risolvere il problema
e nn 
capisco xchč in locale le send e recv funzionino ocorrettamente 
Soluzioni da provare sono + che ben accette :)


 capisco xchè in locale le send e recv funzionino ocorrettamente
Ma ti è stato spiegato. Non c'è nessuna garanzia che i dati trasmessi con 
una singola send vengano letti in una sola recv, né che i dati letti con 
una recv debbano provenire da una singola send. 
Per risolvere il problema devi riscrivere la routine di lettura. A ogni 
ciclo devi scrivere i dati nel buffer senza sovrascrivere quelli già letti 
e tener conto di quanti byte hai letto (valore restituito da recv). Tieni 
inoltre presente, che se il tuo "protocollo" si basa sul riconoscimento 
della stringa "\nFatto", non c'è ovviamente nessuna garanzia che quella 
stringa venga ricevuta interamente con la stessa recv.
Max

Risposte:
Ho fatto una piccola correzione al codice del server e ora la matrice il
client la 
visualizza,
gli ho imposto esplicitamente di sendare solamente i bytes che rappesentano
i 
vettori della matrice
A1 A2 A3
B1 B2 B3
C1 C2 C3
pero' si blocca qui e nn esce ,credo nn riceva o sendi correttamente la condizione
di uscita" \nFatto".
Ah cosi mi si blocca allo stesso modo anche se il client è in locale.
Quindi sia in locale che in remoto cosi il client ha lo stesso comportamento
Riporto il codice cambiato:
[code]
void posti_vuoti(struct posto cine[3][3],int *p)
 { int *pp;
   pp=p;
   unsigned char i,j;
   i='A';
   j='1';
   /*send(ds_sock_acc,"\n\nI posti contrassegnati con le parentesi quadre
sono
già 
assegnati!!\n\n",MAX_DIM,0);*/ per ora sto pezzo l'ho eliminato
   for (i='A'; i<='C'; i++)
     {
 
       for (j='1'; j<='3'; j++)
         {
	   if (*pp==0)
	   if (cine[i-'A'][j-'1'].flag==0)
	     { cine[i-'A'][j-'1'].idPosto[0]=' ';
	       cine[i-'A'][j-'1'].idPosto[3]=' ';
	       send(ds_sock_acc,&cine[i-'A'][j-'1'].idPosto,strlen(cine[i-'A'][j-
'1'].idPosto),0);   /*QUI HO FORZATO A SENDARE ESATTAMENTE LA GIUSTA 
DIMENSIONE CREDO*/
 
	      }
	   else //posto occupato lo stampo tra le parentesi []
	      { cine[i-'A'][j-'1'].idPosto[0]='[';
	        cine[i-'A'][j-'1'].idPosto[3]=']'; 
 
		send(ds_sock_acc,&cine[i-'A'][j-
'1'].idPosto,MAX_DIM,0);
			       }
	       pp=pp+1;
	  }
       }
 
 
      send (ds_sock_acc,"\nFatto",10,0);
};
[/code]
IL codice del client ho provato a cambiarlo,poi ho rinunciato xchè  nn so
come 
forzarlo a ricevere esattamente le dimensioni dei vettori della matrice e
della 
condizione di uscita.
:( :(


Ho provato a risolvere senza succeso , nonostante i tuoi preziosi consigli
nn 
riesco a venirne a capo. HO cercato in internet x ore e ore provando varie
soluzioni :((
Ho provato a cambiare anche il codice del client cosi :(
int dati; 
while (dati=(recv(ds_sock,&buf,MAX_DIM,0))>0); 
tuttavia cmq mi si blocca lo stesso dopo aver visualizzato la matrice xchč
crdo nn 
riceva correttamente la condizione di uscita dal ciclo  
IN rete ho trovato anche una cosa cosi 
while (dati=(recv(ds_sock,&buf,MAX_DIM,0))>0); 
{ buf[dati]='\0';  // che dovrebbe specificare la fine della stringa ricevuta
ma cosi mi si blocca senza nemmeno visualizzare la matrice. 
Ho trovato e provato anche delle funzioni readn e writen ma nn vanno lo stesso.







Mi pare che da nessuna parte hai controllato il valore di ritorno ne' di
send ne' di recv. 
Il problema e` sempre lo stesso, coi socket di norma le operazioni di
lettura e scrittura sono bloccanti, e non e` detto che ti restituiscano o
spediscano i byte che richiedi. Per sapere quanti ne hai davvero
trasferiti devi controllare il valore di ritorno, idem per sapere quanti
ne hai letti.
Dato che l'argomento e` complesso ti consiglio di darti una guardata qui:
http://www.lilik.it/~mirko/gapil/gapilsu238.html
Ciao
Simone
