Newsgroup: it.comp.programmare.win32
Titolo: IsConnected()?

E' possibile sapere se un socket è ancora aperto, cioè se esiste ancora 
una connessione (TCP) tra server e client, senza inviare dati (cioè 
senza ping)?
Il ping dovrebbe già avvenire a livello di protocollo, quindi vorrei 
evitare di aggiungere un ulteriore ping.
Limitazione: Winsock 1.1 con socket in modalità non-blocking.
Kiuhnm

 ha scritto nel messaggio 
news:NeTxe.28914$h5.13...@news3.tin.it...

Prova con la select() mettendo zero come timeout.
Se la select() in lettura restituisce > 0 e poi la la recv() restituisce 
zero, il socket remoto si è chiuso in modo consono.
Comunque, usare un ping può essere utile per verificare che l'applicazione 
dall'altra parte stia girando come dovrebbe.
Se imposti un timeout ad hoc che resetti ad ogni accenno di comunicazione 
non aggiungi traffico quando si sta comunicando.

 zero, il socket remoto si è chiuso in modo consono.
Ho già provato con questo metodo, ma ho dei problemi.
Per il controllo uso FD_ISSET, dato che select() restituisce 0 anche in 
caso di time-out.
Select() non dovrebbe eliminare il socket da fd_set se non rispetta le 
condizioni del "gruppo"?
Il controllo in lettura dà sempre esito negativo (effettivamente non ci 
sono dati da leggere), mentre quello in scrittura dà sempre esito 
positivo. Come posso inviare dati se la connessione è caduta? Forse la 
notifica non è immediata, ma ho aspettato qualche minuto e non c'è 
niente da fare.
Kiuhnm

 ha scritto nel messaggio 
news:eeWxe.29421$h5.13...@news3.tin.it...

Ti posto una parte di codice.
<CODE>
//--------------------------------------------------------------------------------
static int performHasByte(SOCKET sock)
{
  timeval timeout = { 0, 0 };
  fd_set readready;
  FD_ZERO(&readready);
  FD_SET(sock, &readready);
  return select(FD_SETSIZE, &readready, 0, 0, &timeout);
}
//--------------------------------------------------------------------------------
int hasByte(SOCKET sock)
{
  DWORD count = 0;
  int ret;
  do {
    ret = performHasByte(sock);
    if(ret >= 0)
      return ret;
    if(WSAEINPROGRESS == WSAGetLastError()) {
      Sleep(20);
      continue;
      }
    return ret;
    } while(++count < 10);
  return ret;
}
</CODE>
Queste sopra mi servono per sapere se ci sono dati in lettura.
Questa sotto è in un thread che fa un polling (con uno sleep per non 
appesantire).
Ci ho lasciato solo le parti essenziali
<CODE>
//--------------------------------------------------------------------------------
unsigned FAR PASCAL LanCommProc(void* pData)
{
 ....
  while(true) {
  ....
    int nRet = hasByte(Socket);
    if(nRet < 0)
      break;
//------ se ci sono dati in lettura --------------------
    if(nRet > 0) {
   ....
      len = recv(Socket, (LPSTR)buff, len, 0);
      // se len < 0 -> errore, se len == 0 il socket remoto si è chiuso
      if(len <= 0)
        break;
      }
    else
      Sleep(50);
    }
 .....
}
</CODE>
Se vuoi posso inviarti un mio programmino che uso per comunicare con 
seriali, modem e lan per testare dispositivi vari.
Se lo avvio due volte, una come server, l'altra come client lan quando una 
delle due chiude la comunicazione l'altra se ne accorge.
Ciao 

 zero, il socket remoto si è chiuso in modo consono.
Forse ho risolto con recv(MSG_PEEK).
Per come è concepita l'applicazione, il metodo non è ambiguo, anche se 
in generale lo è.
Kiuhnm

 una delle due chiude la comunicazione l'altra se ne accorge.
Il problema è che in modalità non-blocking quel codice non credo 
funzionerebbe. Per es. WSAEINPROGRESS non sarebbe mai restituito e 
inoltre devo poter interrompere qualsiasi operazione istantaneamente e 
WSACancelBlockingCall() è troppo lenta e a volte non sembra funzionare. 
Come ho scritto nell'altro messaggio, la recv() con MSG_PEEK sembra la 
soluzione migliore nel mio caso.
Kiuhnm