NSInputStream / NSOutputStream无法打开

时间:2015-08-24 20:38:40

标签: swift cocoa nsstream

我正在尝试使用NSInputStreamNSOutputStream建立与TCP服务器的连接。 永远不会收到HasBytesAvailableHasSpaceAvailable - 事件。所以我不知道socket实际上是否已经设置好了?

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

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

我已经阅读了SO上的大多数类似帖子并尝试了很多,但没有运气。

如果有人能看到我错过的一些明显的东西,那对我帮助很大! :)

以下是我班级的相关代码:

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 个答案:

答案 0 :(得分:1)

只需在getStreamsToHostWithName方法调用中添加autoreleasepool,因为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)中测试了上述代码 enter 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)")

}
}