2011-07-13 10 views
5

Todos,Transmisión para obtener datos - NSInputStream

Tengo un servidor que tiene un flujo de socket tcp para la comunicación. Necesito llegar a esa corriente y leer los datos iniciales que necesita enviarme.

Mi código actual es el siguiente. Para ser honesto, estoy yendo a esto completamente ciego. No estoy seguro si esto es correcto y mucho menos lo correcto para el trabajo.

-(void) initNetworkCommunication 
{ 
    //input stream 
    NSInputStream *iStream; 
    NSURL *url = [url initWithString:@"192.168.17.1:2004"]; 

    [iStream initWithURL:url]; 
    [iStream setDelegate:self]; 
    [iStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
    [iStream open]; 

} 

Así que desde el modo de ver, este código inicializa la corriente, pero ¿Cómo se leen de la corriente?

Gracias

+1

El bloque de código no parece asignar adecuadamente el objeto 'NSInputStream' (es decir, hay una' 'init' pero sin alloc'). – newenglander

Respuesta

18

Hay dos maneras de obtener datos de una corriente: sondeo y el uso de eventos de flujo.

El sondeo es más simple, pero bloqueará el hilo en el que se está ejecutando. Si utiliza este método, no es necesario que realice las llamadas setDelegate: o scheduleInRunLoop:forMode:. El sondeo se realiza al llamar repetidamente al read:maxLength:.

NSInteger result; 
uint8_t buffer[BUFFER_LEN]; // BUFFER_LEN can be any positive integer 
while((result = [iStream read:buffer maxLength:BUFFER_LEN]) != 0) { 
    if(result > 0) { 
     // buffer contains result bytes of data to be handled 
    } else { 
     // The stream had an error. You can get an NSError object using [iStream streamError] 
    } 
} 
// Either the stream ran out of data or there was an error 

El uso de eventos de transmisión requiere configurar el delegado y agregar la secuencia a un ciclo de ejecución. En lugar de bloquear el hilo, la transmisión enviará un mensaje stream:handleEvent: a su delegado cuando ocurran ciertos eventos, incluso cuando reciba datos. El delegado puede luego recuperar los datos de la transmisión. A continuación se muestra un ejemplo stream:handleEvent: método:

- (void)stream:(NSInputStream *)iStream handleEvent:(NSStreamEvent)event { 
    BOOL shouldClose = NO; 
    switch(event) { 
     case NSStreamEventEndEncountered: 
      shouldClose = YES; 
      // If all data hasn't been read, fall through to the "has bytes" event 
      if(![iStream hasBytesAvailable]) break; 
     case NSStreamEventHasBytesAvailable: ; // We need a semicolon here before we can declare local variables 
      uint8_t *buffer; 
      NSUInteger length; 
      BOOL freeBuffer = NO; 
      // The stream has data. Try to get its internal buffer instead of creating one 
      if(![iStream getBuffer:&buffer length:&length]) { 
       // The stream couldn't provide its internal buffer. We have to make one ourselves 
       buffer = malloc(BUFFER_LEN * sizeof(uint8_t)); 
       freeBuffer = YES; 
       NSInteger result = [iStream read:buffer maxLength:BUFFER_LEN]; 
       if(result < 0) { 
        // error copying to buffer 
        break; 
       } 
       length = result; 
      } 
      // length bytes of data in buffer 
      if(freeBuffer) free(buffer); 
      break; 
     case NSStreamEventErrorOccurred: 
      // some other error 
      shouldClose = YES; 
      break; 
    } 
    if(shouldClose) [iStream close]; 
} 
+0

Esta es una respuesta sumaria valiosa para nosotros los principiantes, y vale la pena editarla: tal como está ahora, con la llamada a 'read: maxLength:' * de NSInputStream dentro de if-stmt, nunca leerá nada si tiene éxito en obtener el buffer interno de la secuencia. Pero no soy lo suficientemente sólido en el tema para editarlo yo mismo, ¿podría arreglarlo, por favor? – Wienke

+0

P.S. Me pregunto por qué NSOutputStream no tiene un método equivalente de 'getBuffer' – Wienke

+1

@Wienke En este ejemplo, la llamada a 'leer: maxLength:' simplemente copia los datos en un búfer temporal creado dentro de la sentencia if. Solo necesita hacer esto si aún no tiene un búfer con los datos que contiene. Inmediatamente después de la instrucción if, debe agregar código para hacer algo con los datos en el búfer, ya que el búfer solo es temporal. Es probable que NSOutputStream no proporcione acceso a un búfer interno porque no permite el acceso a los datos que ya ha escrito, y si escribió directamente en el búfer, no tendría forma de saber que debería enviar esos datos. – ughoavgfhw

Cuestiones relacionadas