NSInputStream / NSOutputStream 未打开

NSInputStream / NSOutputStream not opening

我正在尝试使用 NSInputStreamNSOutputStream 建立与 TCP 服务器的连接。 永远不会收到 HasBytesAvailableHasSpaceAvailable 事件。所以我不知道套接字是否真的设置好了?

在这种特殊情况下,我可以访问服务器并且实际上可以看到它建立了连接,所以我尝试在收到 HasSpaceAvailable 事件之前写入数据并且成功了!

但由于 HasBytesAvailable-事件从未触发,我不知道何时从流中读取。

我已经阅读了大部分关于 SO 的类似帖子并尝试了其中的很多,但没有成功。

如果有人能看到我遗漏的明显内容,那将对我有很大帮助! :)

下面是我的相关代码class:

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?")
        }

    }        

}

只需在 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_redirect) 中测试了上面的代码

或者你也可以使用 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)")

}
}