2015-08-24 55 views
3

我想建立一個連接到TCP服務器,與NSInputStreamNSOutputStreamHasBytesAvailableHasSpaceAvailable - 事件永遠不會收到。所以我不知道套接字是否真的被設置了?NSInputStream/NSOutputStream不開放

在這種特殊情況下,我可以訪問服務器,並且實際上可以看到它建立了連接,所以我試圖在收到HasSpaceAvailable事件之前寫入數據並且它工作正常!

但由於HasBytesAvailable -event從來沒有觸發我不知道什麼時候從流中讀取。

雖然我已經閱讀了大部分類似的帖子,並嘗試了很多,但沒有運氣。

如果任何人都能看到我錯過的東西,那對我很有幫助! :)

下面是我班上的相關代碼:

class TCPConnection : NSObject, NSStreamDelegate { 


    private var host: String 
    private var port: Int 
    private var inputStream: NSInputStream? 
    private var outputStream: NSOutputStream? 
    private var readyToWrite = true 

    init(host: String, port: Int) { 
     self.host = host 
     self.port = port 

     super.init() 

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

     inputStream!.delegate = self 
     outputStream!.delegate = self 

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

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

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

      case NSStreamEvent.EndEncountered: 
       print("EndEncountered: \(aStream.streamError?.description)") 
       break 

      case NSStreamEvent.HasBytesAvailable: 
       print("HasBytesAvailable") 
       break 

      case NSStreamEvent.None: 
       print("None") 
       break 

      case NSStreamEvent.OpenCompleted: 
       print("opened!") 
       break 

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

      case NSStreamEvent.EndEncountered: 
       print("EndEncountered: \(aStream.streamError?.description)") 
       break 

      case NSStreamEvent.HasSpaceAvailable: 
       print("HasSpaceAvailable") 
       break 

      case NSStreamEvent.None: 
       print("None") 
       break 

      case NSStreamEvent.OpenCompleted: 
       print("opened!") 
       break 

      default: 
       print("default") 
      } 
     } else { 
      print("another stream?") 
     } 

    }   

} 
+1

這對我的作品。你在使用操場嗎?你需要'NSRunLoop.mainRunLoop()。run()'。 – jtbandes

+0

你在使用什麼類型的服務器?在某些情況下,你將需要包括'/ N' ** **或'/ N/r',另闢蹊徑,TCP是第三方API,例如[CocoaAsyncSocket(https://github.com/robbiehanson/CocoaAsyncSocket) – Xrait

回答

1

只需添加autoreleasepool的getStreamsToHostWithName方法調用內部自NSStream釋放當塊執行完畢

autoreleasepool { 
     NSStream.getStreamsToHostWithName(self.host, port: self.port, inputStream: &inputStream, outputStream: &outputStream) 
} 

我已經測試以上代碼在xcode7 beta 4和SocketTest工具中(http://sourceforge.net/projects/sockettest/?source=typ_redirectenter image description here

另外,您還可以使用CFStreamCreatePairWithSocketToHost API

class TCPConnection: NSObject, NSStreamDelegate { 
    var host:String? 
    var port:UInt32? 
    var inputStream: NSInputStream? 
    var outputStream: NSOutputStream? 
    var status = false; 
    var output = "message" 
    var bufferSize = 1024; 
init(host: String, port:UInt32){ 
    self.host = host 
    self.port = port 
    self.status = false 
    output = "" 
    super.init() 
} 

func stream(aStream: NSStream, handleEvent aStreamEvent: NSStreamEvent) { 
    switch aStreamEvent { 

    case NSStreamEvent.OpenCompleted: 
     print("OpenCompleted") 
     break 

    case NSStreamEvent.HasBytesAvailable: 
     print("HasBytesAvailable") 
     break 

    case NSStreamEvent.HasSpaceAvailable: 
     print("HasSpaceAvailable") 
     break 

    case NSStreamEvent.EndEncountered: 
     print("EndEncountered") 

     //   aStream.close() 
     aStream.removeFromRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode) 
     break 

    case NSStreamEvent.None: 

     break 

    case NSStreamEvent.ErrorOccurred: 

     break 

    default: 
     print("# something weird happend") 
     break 
    } 
} 

func connect() { 
    print("# connecting to \(host):\(port)") 
    var cfReadStream : Unmanaged<CFReadStream>? 
    var cfWriteStream : Unmanaged<CFWriteStream>? 

    CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, host, port!, &cfReadStream, &cfWriteStream) 
    inputStream = cfReadStream!.takeRetainedValue() 
    outputStream = cfWriteStream!.takeRetainedValue() 

    inputStream!.delegate = self 
    outputStream!.delegate = self 

    inputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode) 
    outputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode) 

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


func read(){ 
    var buffer = [UInt8](count: bufferSize, repeatedValue: 0) 
    output = "" 
    while (self.inputStream!.hasBytesAvailable){ 
     var bytesRead: Int = inputStream!.read(&buffer, maxLength: buffer.count) 
     if bytesRead >= 0 { 
      output += NSString(bytes: UnsafePointer(buffer), length: bytesRead, encoding: NSASCIIStringEncoding)! as String 
     } else { 
      print("# error") 
     } 
     print("> \(output)") 
    } 
} 

func send(message:String){ 
    let data:NSData = message.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)! 
    let bytesWritten = self.outputStream!.write(UnsafePointer(data.bytes), maxLength: data.length) 
    print("< send to \(host)") 

} 
} 
+0

我嘗試了這兩種解決方案,仍然沒有結果! –

+0

確保您的TCPConnection實例很強大。確保你的服務器設置正確 –

+0

@Ndushi我通過在SocketTest工具(http://sourceforge.net/projects/sockettest/?source=typ_redirect)上添加autoreleasepool來測試你的代碼,它的工作正常。請檢查您的服務器部分。 –