2015-02-22 7 views
5

TL; DR: Qual è il modo per verificare se il flusso remoto viene aperto correttamente dopo una chiamata a NSStream.getStreamsToHostWithName(...)?Come verificare se la mia presa remota NSStream è correttamente aperta

La mia applicazione è un'applicazione mobile IOS8 swift.

sto usando NSStream comunicazione presa di ingresso ed uscita con un server remoto.

per la connessione al server e aprire il mio flusso io uso questo codice:

func connect(host: String, port: Int) -> Bool 
{ 
    //clear the previous connection if existing (and update self.connected) 
    disconnect() 
    //updating the current connection 
    self.host = host 
    self.port = port 

    //pairing NSstreams with remote connection 
    NSStream.getStreamsToHostWithName(self.host!, port: self.port!, inputStream: &inputStream, outputStream: &outputStream) 

    if (self.inputStream != nil && self.outputStream != nil) 
    { 
     //open streams 
     self.inputStream?.open() 
     self.outputStream?.open() 
    } 
    if self.outputStream?.streamError == nil && self.inputStream?.streamError == nil 
    { 
     println("SOK") //PROBLEM 1 
    } 
    //error checking after opening streams // PROBLEM 2 
    if var inputStreamErr: CFError = CFReadStreamCopyError(self.inputStream)? 
    { 
     println("InputStream error : " + CFErrorCopyDescription(inputStreamErr)) 
    } 
    else if var outputStreamErr: CFError = CFWriteStreamCopyError(self.outputStream)? 
    { 
     println("OutStream error : " + CFErrorCopyDescription(outputStreamErr)) 
    } 
    else 
    { 
     //set the delegate to self 
     self.inputStream?.delegate = self 
     self.outputStream?.delegate = self 
     self.connected = true 
    } 
    //return connection state 
    return self.connected 
} 

Il mio problema si trova in // // PROBLEM1 e PROBLEM2.

In questi punti, provo a determinare se i miei socket sono aperti correttamente, ma anche se il server non sta eseguendo questo codice funziona ancora, quindi le operazioni di lettura e scrittura falliscono. Mi piacerebbe essere in grado di determinare se la connessione è fallita o meno.

Forse lo sto facendo completamente storto, non capisco come testarlo.

risposta

27

Prima di tutto, bisogna schedule the stream on a runloop:

inputStream!.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode) 
outputStream!.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode) 

E, nel codice, è troppo presto per verificare l'errore. Perché open() è un'operazione asincrona, devi aspettare il risultato usando delegate. Qui è esempio di lavoro:

import Foundation 

class Connection: NSObject, NSStreamDelegate { 
var host:String? 
var port:Int? 
var inputStream: NSInputStream? 
var outputStream: NSOutputStream? 

func connect(host: String, port: Int) { 

    self.host = host 
    self.port = port 

    NSStream.getStreamsToHostWithName(host, port: port, inputStream: &inputStream, outputStream: &outputStream) 

    if inputStream != nil && outputStream != nil { 

     // Set delegate 
     inputStream!.delegate = self 
     outputStream!.delegate = self 

     // Schedule 
     inputStream!.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode) 
     outputStream!.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode) 

     print("Start open()") 

     // Open! 
     inputStream!.open() 
     outputStream!.open() 
    } 
} 

func stream(aStream: NSStream, handleEvent eventCode: NSStreamEvent) { 
    if aStream === inputStream { 
     switch eventCode { 
     case NSStreamEvent.ErrorOccurred: 
      print("input: ErrorOccurred: \(aStream.streamError?.description)") 
     case NSStreamEvent.OpenCompleted: 
      print("input: OpenCompleted") 
     case NSStreamEvent.HasBytesAvailable: 
      print("input: HasBytesAvailable") 

      // Here you can `read()` from `inputStream` 

     default: 
      break 
     } 
    } 
    else if aStream === outputStream { 
     switch eventCode { 
     case NSStreamEvent.ErrorOccurred: 
      print("output: ErrorOccurred: \(aStream.streamError?.description)") 
     case NSStreamEvent.OpenCompleted: 
      print("output: OpenCompleted") 
     case NSStreamEvent.HasSpaceAvailable: 
      print("output: HasSpaceAvailable") 

      // Here you can write() to `outputStream` 

     default: 
      break 
     } 
    } 
} 

} 

Poi:

let conn = Connection() 
conn.connect("www.example.com", port: 80) 
+0

Grazie per questa risposta precisa. Ho solo alcune domande. Innanzitutto, la parte relativa alla pianificazione rende i flussi asincroni? Voglio che le mie operazioni siano sincrone. –

+0

A mio parere, il flusso stesso è sempre non bloccante. Se è necessaria l'operazione sincrona, è necessario utilizzare il polling con il ciclo 'while true {...}'. vedere: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Streams/Articles/PollingVersusRunloop.html – rintaro

+1

Penso che il flusso stia bloccando, l'operazione NSInputStream.read() sta bloccando di default –

Problemi correlati