Azzurra IRC Network Forum

[C]problema con send e recv in remoto

viridovix · 27/08/2005 23:59 · #1
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.(stesso codice del 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.

struct posto
{
unsigned char idPosto[6]; // i caratteri che indicano fila e posto sono
memo qui
int *flag; // flag poso libero/prenotato
};




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';
}
};


di seguito il codice del server che spedisce la matrice vettore x vettore al client.


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);
};


ora codice funzione visualizza matrice del client:


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);

};


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 il client 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) funziona, da remoto no :(
Non riesco a capire come mai le send e recv nn funzionino a dovere con la connessione in remoto .
Qualcuna spero mi sappia aiutare. C'è un modo x controllare il giusto flusso di dati x garantire la giusta visualizzazione ????????
Progeny · 15/09/2005 11:56 · #2
Premettendo che non letto il codice, se in locale funziona tutto, credo sia corretto (anche dal punto di vista logico).
Per controllare il flusso dei dati, uoi usare tcpdump.
Magari può essere un problema di routing, tipo se sul tuo pc sono impostati due default gateway...
route -n
e controlla.
MeDevil · 27/10/2005 21:33 · #3
è normale che non funzioni...

con questa send:

send(ds_sock_acc, &cine[i-'A'][j-'1'].idPosto, MAX_DIM, 0);

stai inviando al server l'indirizzo della prima locazione di memoria della matrice dei posti (mi pare fosse di 6 char). prova togliendo il & prima di cine[ etc etc].

Spero sia utile...
sottovento · 21/11/2005 10:22 · #4
Nel codice c'e' qualcosa da sistemare. In effetti non avrebbe mai dovuto funzionare.

Il problema numero 1 e' la recv(). Non controlli il ritorno, dando per scontato che venga letto il numero esatto di byte (fra l'altro, variabile senza che il ricevente possa sapere quando un messaggio e' completato). Esiste un flag (MSG_WAITALL) da mettere al posto dell'ultimo parametro (quello che hai posto a 0) per ottenere il numero esatto di byte.
Cmq nemmeno questo ti assicura di leggere tutto correttamente, dovresti controllare anche se non ci sono stati errori. Oltre, ovviamente, a spedire qualche informazione in piu', che so, il numero di byte di cui e' composto il messaggio.

Ti funziona quando 'gira' tutto sulla stessa macchina poiche' i messaggi che spedisci sono tali da rientrare in un solo pacchetto. Abbastanza fortunato, direi.

Come ultima cosa, ti consiglio di fare in modo che le due strcmp() siano uguali. Se pero' ci pensi, potresti trovare una soluzione piu' efficace, non ultima quella di ridurre il numero di questi controlli ad uno solo.

Per prima cosa, pero', controlla la recv. Analogamente devi gestire gli errori di invio. Non darli per scontati, poi non funziona niente e non sai perche'.

Spero di esser stato utile.
Ciao ciao
sottovento