PDA

View Full Version : Windows CE - Aiuto Socket


SimonJ
04-11-2010, 09:33
Salve a tutti, desidererei chiedere il vostro aiuto per questa questione. Sto sviluppando un software di controllo in real-time su Windows CE 6.0.
Esso si compone di diversi thread, in cui uno di questo gestisce la comunicazione di rete. Uso le MessageQueue come metodo d’intercomunicazione tra thread.

Al momento l’applicativo da me sviluppato funziona egregiamente, a parte la comunicazione bidirezionale attraverso la rete. Fino ad ora, nel thread che gestisce la comunicazione, eseguivo il seguente codice, in altre parole ricevevo i comandi da un socket TCP riuscendo a gestire eventuali disconnessioni:

while(1) {

if (stateCommunication)
{
receiveCommand();
}
else
{
waitForConnection();
}
}


All’interno della funzione receiveCommand() richiamavo la recv() e successivamente procedevo all’elaborazione del comando ricevuto. Ora mi ritrovo con il problema che la recv() blocca l’esecuzione del programma fintanto che non arriva un nuovo comando. Al fine di risolvere questo problema ho provato ad inserire le seguenti istruzioni, con l’intenzione di non eseguire la rev() in presenza di un timeout, ma senza alcun risultato.

FD_ZERO(&fdread);
FD_SET(remoteSocket, &fdread);
if (select(NULL,&fdread,NULL,NULL,&timeSelect)>0) {
(…)
}

oltre che a:

FD_ZERO(&fdread);
FD_SET(remoteSocket, &fdread);

if (FD_ISSET(remoteSocket,&fdread)) {
(…)
}

e:
unsigned long socketBlock=1;
(…)
if (ioctlsocket(remoteSocket,FIONBIO,&socketBlock)==0) {
(…)
}

Come potrei risolvere? Avrei pensato alla seguente strategia: ovvero scomporre la ricezione e l’invio di dati in due thread opportunamente accordati dal thread principale di comunicazione, mediante una MessageQueue bidirezionale. Potrebbe essere una strategia vincente, anche al fine di limitare i ritardi tra invio e processo dei comandi, o solamente un inutile spreco di risorse?

Teo@Unix
04-11-2010, 10:35
Ciao, vedo che vai a settare il socket come non-bloccante.
Ma questo lo fai contemporaneamente a select()? Io ho risolto problemi di questo tipo utilizzando select() e recv() bloccante. Utilizzando appunto un timeout.

Ad esempio avevo utilizzato questa configurazione per gestire una quantità di dati in arrivo che non è conosciuta a priori... il ciclo esce quando il socket viene chiuso correttamente, oppure allo scadere di un timeout.

// Response
while(1) {
FD_ZERO(&readfd);
FD_SET(sock,&readfd);
if((RetVal = select(NULL,&readfd,NULL,NULL,&tv)) == 0) {
cerr << "Error: select() timeout" << endl; // Timeout on recv
return(ERROR_CODE);
}
else if (RetVal == SOCKET_ERROR) {
cerr << "Error: " << WSAGetLastError() << endl;
return(ERROR_CODE);
}
if(FD_ISSET(sock,&readfd)) {
RetVal = recvfrom(sock,response,RECV_BUF-1,0,(struct sockaddr*)&server,(int*)&size_addr);
if(RetVal == SOCKET_ERROR) { // Error
cerr << "Error: " << WSAGetLastError() << endl;
return(ERROR_CODE);
}
if(RetVal == 0) break; // Grateful close
}
cout << response;
memset(response,0,RECV_BUF);
}

La soluzione che proponi è più complessa ma non credo impossibile... non saprei, direi che potresti prima provare in questo modo adattando l'esempio...
Perchè se io non capito male, impostando la recv() non bloccante questa ritorna subito, troppo velocemente senza dati....

SimonJ
04-11-2010, 10:42
No, non ho settato il socket come non bloccante ed utilizzato la select(): prima una prova, poi l'altra..

Teo@Unix
04-11-2010, 10:49
No, non ho settato il socket come non bloccante ed utilizzato la select(): prima una prova, poi l'altra..

ho capito, quindi che problemi hai con select(), in teoria dovrebbe risolverti il problema, se select() torna 0 allora gestirai il caso del timeout...

SimonJ
04-11-2010, 12:39
Praticamente, select() non mi va mai a 0, mi restitisce sempre -1; ho impostato il timeout sia a 1s, 500ms, ecc..

SimonJ
04-11-2010, 13:01
Ho fatto un "Pulisci soluzione" ed un "Rigenera soluzione" ed ora il select() sembra funzionare!
Il problema, ora, è che la prima recv() mi restituisce -1, facendo andare il software in attesa di un'altra connessione..

Teo@Unix
04-11-2010, 13:13
... prova a capire di che si tratta con GetLastError().

SimonJ
04-11-2010, 13:24
Mi restituisce l'errore 10038 (WSAENOTSOCK-socket operation on non-socket)..

SimonJ
04-11-2010, 13:52
Quest'ultimo errore era dovuto al fatto che non gestivo la condizione di ritorno a 0 di recv(). Per fortuna ora tutto va! Grazie ancora!
Un po' mi secca per le ore perse, quando bastava una semplice ricompilazione..strano, però..