2012-04-10 16 views
5

Tengo una aplicación que estoy escribiendo para Windows 8/WinRT que usa la API de StreamSocket para hacer una conexión de transmisión a un servidor. Es decir, el servidor transmite datos al cliente, a veces con metaetiquetas, y puede desconectarse en cualquier momento.Manejo de WinRT StreamSocket se desconecta (tanto del lado del servidor como del cliente)

El problema que tengo es que no tengo idea de cómo detectar cuando el servidor se ha desconectado. No parece haber ningún evento o propiedad en la clase StreamSocket, ya sea en sus flujos de entrada o salida, o en las clases DataReader/DataWriter que tienen algo que ver con el estado de la conexión.

Además de eso, el método DataReader ReadAsync no está fallando después de que el servidor se desconecta del cliente. En cambio, la operación tiene éxito hasta donde yo sé, y los datos que llena en su búfer son solo lo último que le envió el servidor (es decir, no está borrando su búfer interno, aunque puedo ver que se ha "consumido") el búfer cada vez que llamo ReadByte). Lo hace para cada llamada posterior a ReadAsync, rellenando el búfer con lo que el servidor envió la última vez que se desconectó. Aquí es una versión simplificada del código:

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

Respuesta

9

Es decir, los flujos de datos del servidor al cliente, a veces con etiquetas meta, y puede desconectarse en cualquier momento. El problema que tengo es que no tengo idea de cómo detectar cuándo el servidor se ha desconectado.

Un codo "elegante" puede detectarse por el otro lado como una lectura de longitud 0. Es decir, simplemente actúa como un final de transmisión regular.

Un cierre de socket "abortivo" es más complicado. Usted have to send data para detectar que el otro lado se ha cerrado, y una vez que la escritura falla, las lecturas o escrituras adicionales deben fallar (con una excepción). Si su protocolo no le permite enviar datos, entonces tendrá que asumir que la conexión es mala después de que expire el tiempo de espera y simplemente cerrarla. :(

Dependiendo de la aplicación del cierre del enchufe "fallido" puede ser normal, - en particular, los servidores muy ocupados pueden ser escritos para sujetar cerrar sus conexiones, ya que les permite recuperar los recursos más rápidamente (evitando el cuatro toma de -paso apagado apretón de manos).

no parecen ser hechos o propiedades en la clase StreamSocket, o bien sus flujos de entrada o salida, o en las/DataWriter clases DataReader que tienen algo que ver con la conexión estado.

DataReader/DataWriter no se preocupan por las "conexiones". Realmente son solo BitConverter, solo que esta vez se diseñaron mejor.

Supongo que el motivo StreamSocket no tiene una propiedad "conectado" es porque Socket.Connected is nearly useless and definitely misleading.


me gustaría probar usando StreamSocket.InputStream.ReadAsync directamente en lugar de utilizar DataReader, ya que apenas está leyendo bytes de todos modos. Parece que ha descubierto un error en DataReader, que debe informar en Microsoft Connect si InputStream.ReadAsync funciona como se esperaba. También vea this related forum post.

+1

Esta es una buena información que debe saber.Gracias. Parece que el problema de DataReader.ReadAsync es un error, y parece que el equipo apropiado dentro de Microsoft está al tanto, así que con suerte se solucionará. Mientras tanto, intenté su sugerencia de llamar a InputStream.ReadAsync en mi propio IBuffer (desde WindowsRuntimeBuffer.Create), y no solo funcionó, sino que parece haber reducido la latencia en una cantidad notable. –

+0

encontró esta publicación anterior. @JeremyBell ¿Cuál es el error de voz del usuario que abriste sobre 'InputStream.ReadAsync'? ¿Ya está resuelto? También parece tener un comportamiento extraño en mi flujo de entrada que sigue acumulando respuestas del servidor que no deberían estar allí. Quiero leer todos los datos del socket antes de enviar nuevos datos al servidor. Consulte 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

Cuestiones relacionadas