PDA

View Full Version : [C++] socket, select() e broadcast UDP


nrk985
20-03-2007, 14:03
Ho un problema:
In un'applicazione server che ascolta dei broadcast su una porta UDP, spediti da un mio client, la funzioen select() non si "accorge" quando arrivano.
Il pacchetto effettivamente arriva, e l'ho determinato sia usando Wireshark su una macchina nella rete, sia leggendo direttamente senza fare la select: i dati arrivano e ci son tutti.
Inoltre, il client ascolta sempre dallo stesso socket le eventuali risposte dei server usando sempre la funzione select(), e quando invio il broadcast, gli ritorna indietro lo stesso e la select in questo caso funziona correttamente!!
Il server è un cellulare con windows mobile (Windows CE 5.0) collegato alla rete col wireless, ma non mi risulta che ci siano differenze di funzionamento dei sockets di rete, e in ogni caso il pacchetto arriva, come già spiegato.

ecco il codice del server:
announcer = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(VC_ANNOUNCE_PORT);
sin.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
int err=bind(announcer, (sockaddr*)&sin, sizeof sin);
BOOL broadcast=TRUE;
err=setsockopt(announcer, SOL_SOCKET, SO_BROADCAST, (char*)&broadcast, sizeof broadcast);

fd_set rs;
timeval t;
t.tv_sec=1;
t.tv_usec=0;

while (!vcclosing)
{
FD_ZERO(&rs);
FD_SET(announcer,&rs);
int n = select(NULL, &rs, NULL, NULL, &t);
if (n)
{ // N è sempre zero e scade sempre il timeout!!
...
}
}


sbaglio quialcosa nelle inizializzazioni??? :help:

ilsensine
20-03-2007, 14:57
Non ho idea, ma ti consiglio di controllare per scrupolo una cosa con cui mi sono già scornato: controlla che il tuo socket announcer abbia un valore _inferiore_ a FD_SETSIZE. Avendo portato alcuni programmi sotto windows, ho avuto la spiacevole sorpresa di constatare come spesso e volentieri i socket ottengono un valore superiore, già all'avvio del programma.

nrk985
20-03-2007, 18:50
Non ho idea, ma ti consiglio di controllare per scrupolo una cosa con cui mi sono già scornato: controlla che il tuo socket announcer abbia un valore _inferiore_ a FD_SETSIZE. Avendo portato alcuni programmi sotto windows, ho avuto la spiacevole sorpresa di constatare come spesso e volentieri i socket ottengono un valore superiore, già all'avvio del programma.
ma è importante? ti riferirci anche al fatto che il primo parametro della select è NULL? no, perché in windows va così...
mi pare che nel client con xp l'id del socket sia sull'ordine del migliaio, mentre su WinCE sia minore di 10. quando riaccendo il pc controllo, ora sto scrivendo proprio dal cellulare.

se fosse superiore, cosa dovrei fare?
comunque, non trovi nulla di sbagliato nel codice che ho postato, per ricevere dei broadcast? se hai soluzioni alternative sono ben accette! ovviamente che non facciano uso di polling sfrenato, che altrimenti il povero processorino TI 200mhz non regge :D

grazie e saluti

nrk985
21-03-2007, 11:17
up!!! :help:

ilsensine
22-03-2007, 08:16
-- doppio

ilsensine
22-03-2007, 08:17
ma è importante?

ti riferirci anche al fatto che il primo parametro della select è NULL?
Non lo avevo notato, è chiaramente un altro errore. Il primo parametro della select è un numero che indica il numero di descrittori da monitorare (o il valore del descrittore più alto + 1, se vuoi). Nel tuo caso, metti announcer+1.
mi pare che nel client con xp l'id del socket sia sull'ordine del migliaio, mentre su WinCE sia minore di 10. quando riaccendo il pc controllo, ora sto scrivendo proprio dal cellulare.
Sì dovrebbe essere così. Su WinCE non dovresti avere problemi legati a FD_SETSIZE, su XP sì.

se fosse superiore, cosa dovrei fare?
#define FD_SETSIZE 16384 _prima_ degli #include e passa la paura.

nrk985
22-03-2007, 11:34
Dall'msdn, http://msdn2.microsoft.com/en-us/library/ms740141.aspx
nfds
[in] Ignored. The nfds parameter is included only for compatibility with Berkeley sockets.

Cmq ho capito dove stava l'errore, e avrei un'altra domanda :D
In pratica quando il cell è connesso tramite Activesync al computer, lui vede un'altra interfaccia di rete con IP 192.168.2.1, che è quella che usa activesync per scambiare i dati.
La bind fatta in quel modo evidentemente bindava a quell'interfaccia, ho provato a inviare un broadcast DAL cellulare e nel campo sorgente c'era l'ip sbagliato... fatto stà che uando scollego il cellulare allora comincia a funzionare.
Ora vorrei sapere qual'è un metodo sicuro per avere gli IP delle interfacce d rete installate sul cellulare, dato che di metodi ne ho visti 100 tutti basati sul dns, etc.... che non mi pare il massimo...

ciao e grazie 2000...

ilsensine
22-03-2007, 11:52
Dall'msdn, http://msdn2.microsoft.com/en-us/library/ms740141.aspx
nfds
[in] Ignored. The nfds parameter is included only for compatibility with Berkeley sockets.
Ah, non lo sapevo. Rimane valido il discorso su FD_SETSIZE.

Ora vorrei sapere qual'è un metodo sicuro per avere gli IP delle interfacce d rete installate sul cellulare, dato che di metodi ne ho visti 100 tutti basati sul dns, etc.... che non mi pare il massimo...

Non sono così pratico di windows per poterti rispondere qui...

nrk985
22-03-2007, 14:49
Ah, non lo sapevo. Rimane valido il discorso su FD_SETSIZE.


Non sono così pratico di windows per poterti rispondere qui...
Fa niente, magari risponderà qualcun'altro.
Anche se penso che il metodo sia uguale sia per windows, che per linux, dato che si useranno sempre le socket, o sbaglio?

grazie cmq
ciao

ilsensine
22-03-2007, 15:02
L'aggancio a uno stream broadcast dovrebbe essere uguale; l'individuazione dell'ip di una interfaccia come avevi richiesto è ovviamente differente.

ilsensine
22-03-2007, 15:16
C'è una cosa che mi suona strana, ora che vedo...non dovresti effettuare nel client una IP_ADD_MEMBERSHIP?

nrk985
22-03-2007, 17:30
C'è una cosa che mi suona strana, ora che vedo...non dovresti effettuare nel client una IP_ADD_MEMBERSHIP?
quella la devi usare quando fai multicast, nn broadcast....
cmq il problema ormai è risolto, penso che farò a meno di fare del debug :(