2012-04-10 22 views
5

Ho un'applicazione che sto scrivendo per Windows 8/WinRT che utilizza l'API StreamSocket per eseguire una connessione streaming a un server. Vale a dire, il server trasmette i dati al client, a volte con meta tag e può disconnettersi in qualsiasi momento.Gestione di WinRT StreamSocket disconnette (lato server e lato client)

Il problema che sto avendo è che non ho idea di come rilevare quando il server si è disconnesso. Non sembrano esserci eventi o proprietà sulla classe StreamSocket, né i suoi flussi di input o output, né sulle classi DataReader/DataWriter che hanno qualcosa a che fare con lo stato della connessione.

Per di più, il metodo DataReader ReadAsync non ha esito negativo dopo che il lato server si è disconnesso dal client. Invece, l'operazione ha esito positivo per quanto posso dire, e i dati che riempie nel suo buffer sono solo l'ultima cosa che il server ha inviato ad esso (cioè non sta cancellando il suo buffer interno, anche se posso vedere che ha "consumato" il buffer ogni volta che chiamo ReadByte). Lo fa per ogni chiamata successiva a ReadAsync: ricarica il buffer con ciò che il server ha inviato l'ultima volta prima della disconnessione. Ecco una versione semplificata del codice:

public async Task TestSocketConnectionAsync() 
    { 
     var socket = new StreamSocket(); 
     await socket.ConnectAsync(new HostName(Host), Port.ToString(), 
      SocketProtectionLevel.PlainSocket); 
     var dr = new DataReader(socket.InputStream); 
     dr.InputStreamOptions = InputStreamOptions.Partial; 

     this.cts = new CancellationTokenSource(); 
     this.listenerOperation = StartListeningAsync(dr, cts); 
    } 

    public async Task StartListeningAsync(DataReader dr, CancellationTokenSource cts) 
    { 
     var token = cts.Token; 
     while (true) 
     { 
      token.ThrowIfCancellationRequested(); 
      var readOperation = dr.LoadAsync(1024); 
      var result = await readOperation; 
      if (result <= 0 || readOperation.Status != Windows.Foundation.AsyncStatus.Completed) 
      { 
       cts.Cancel(); // never gets called, status is always Completed, result always > 0 
      } 
      else 
      { 
       while (dr.UnconsumedBufferLength > 0) 
       { 
        byte nextByte = dr.ReadByte(); 

        // DriveStateMachine(nextByte); 
       } 
      } 
     } 
    } 

risposta

9

Vale a dire, i flussi di dati server al client, a volte con meta tag, e può staccare in qualsiasi momento. Il problema che sto avendo è che non ho idea di come rilevare quando il server si è disconnesso.

Una chiusura "elegante" può essere rilevata dall'altro lato come una lettura di lunghezza 0. Cioè, si comporta come un normale end-of-stream.

Una chiusura "abortiva" della presa è più complicata. È have to send data per rilevare che l'altro lato è stato chiuso e una volta che la scrittura non riesce, eventuali letture o scritture aggiuntive non dovrebbero riuscire (con un'eccezione). Se il tuo protocollo non ti consente di inviare dati, dovrai supporre che la connessione non sia buona dopo la scadenza di un timeout e semplicemente chiuderla. :(

seconda dell'applicazione "abortiva" chiusura presa può essere normale - in particolare, i server molto occupati possono essere scritti per bloccare chiudere le loro connessioni, perché permette loro di recuperare le risorse in modo più rapido (evitando la quattro presa -step arresto handshake).

ci non sembrano essere eventi o proprietà nella classe StreamSocket, né i suoi flussi in entrata o in uscita, o sui DataReader/DataWriter classi che hanno a che fare con collegamento

DataReader/DataWriter non sono interessati alle "connessioni". Sono in realtà solo BitConverter, solo progettate meglio questa volta.

Direi che il motivo StreamSocket non ha una proprietà "connessa" è perché Socket.Connected is nearly useless and definitely misleading.


Vorrei provare a utilizzare StreamSocket.InputStream.ReadAsync direttamente invece di utilizzare DataReader, dal momento che si sta solo leggendo byte in ogni caso. Sembra che tu abbia scoperto un bug in DataReader, che dovresti segnalare su Microsoft Connect se InputStream.ReadAsync funziona come previsto. Vedi anche this related forum post.

+1

Questa è una buona informazione da sapere.Grazie. Sembra che il problema DataReader.ReadAsync sia un bug, e sembra che il team appropriato in Microsoft ne sia a conoscenza, quindi speriamo che venga risolto. Nel frattempo, ho provato il tuo suggerimento di chiamare InputStream.ReadAsync sul mio IBuffer (da WindowsRuntimeBuffer.Create), e non solo ha funzionato, ma sembra avere una latenza ridotta di una quantità notevole. –

+0

ha trovato questo vecchio post. @JeremyBell qual è il bug vocale dell'utente che hai aperto su 'InputStream.ReadAsync'? È risolto? Inoltre, sembra che il mio flusso di input abbia un comportamento strano che continua a accumulare risposte dal server che non dovrebbe essere presente. Voglio leggere tutti i dati dal socket prima di inviare nuovi dati al server. Vedi http://stackoverflow.com/questions/27533703/how-to-read-all-the-available-data-from-a-winrt-streamsocket-and-empty-the-input?noredirect=1#comment43496033_27533703 – philk

Problemi correlati