我正在尝试用一个NSInputStream和一个NSOutputStream建立到TCP服务器的连接。
从未接收到HasBytesAvailableHasSpaceAvailable事件。所以我不知道插座是否真的安装好了?
在这种特殊情况下,我可以访问服务器,并且可以看到它正在建立连接,因此我尝试在收到HasSpaceAvailable事件之前写入数据,但它起作用了!
但由于HasBytesAvailable-事件从不触发,我不知道何时从流中读取数据。
我读过很多类似的帖子,尝试过很多,但没有运气。
如果有人能看到我错过的东西,那将对我大有帮助!:)
以下是我班的相关代码:

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方法调用中添加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
swift - NSInputStream/NSOutputStream无法打开-LMLPHP
或者,您也可以使用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)")

}
}

10-06 11:01