在Swift中从NSInputStream接收数据

18

我试图在Swift中使用NSOutputStream和NSInputStream发送和接收数据。发送数据的操作很好,但是我对接收数据有一些疑问。

我找到了一种处理NSStreamEvent的解决方案,并且我已经尝试过了。

首先,这是我的初始化连接函数:

func initNetworkCommunication(){  
    var host : CFString = "127.0.0.1"
    var port : UInt32 = 7001
    var readstream : Unmanaged<CFReadStream>?
    var writestream : Unmanaged<CFWriteStream>?
    CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, host, port, &readstream, &writestream)

    inputstream = readstream!.takeRetainedValue()
    outputstream = writestream!.takeRetainedValue()

    inputstream.delegate = self
    outputstream.delegate = self


    inputstream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
    outputstream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)

    inputstream.open()
    outputstream.open()   
}

这部分代码是有效的。我已经将委托设置为 self,因此应该能够在这个类中处理 NSStreamEvents。

func stream(aStream: NSStream, handleEvent eventCode: NSStreamEvent) {
    switch (eventCode){
    case NSStreamEvent.OpenCompleted:
        NSLog("Stream opened")
        break
    case NSStreamEvent.HasBytesAvailable:
        NSLog("HasBytesAvailable")
        break
    case NSStreamEvent.ErrorOccurred:
         NSLog("ErrorOccurred")
        break
    case NSStreamEvent.EndEncountered:
        NSLog("EndEncountered")
        break
    default:
        NSLog("unknown.")
    }
}

据我理解,每当有数据到达时,它应该打印“HasBytesAvaible”,但是每次都打印“unknown.”。因此,我稍微尝试了一下,并且使用以下方法解决了问题:

func stream(aStream: NSStream, handleEvent eventCode: NSStreamEvent) {

    var buffer = [UInt8](count: 4096, repeatedValue: 0)
    while (inputstream.hasBytesAvailable){
        let result: Int = inputstream.read(&buffer, maxLength: buffer.count)
    }

    switch (eventCode){
    case NSStreamEvent.OpenCompleted:
        NSLog("Stream opened")
        break
    case NSStreamEvent.HasBytesAvailable:
        NSLog("HasBytesAvailable")
        var output = NSString(bytes: &buffer, length: buffer.count, encoding: NSUTF8StringEncoding)
        NSLog("output: %@", output)
        receiveMessage(output) //only adds the message to an array
        break
    case NSStreamEvent.ErrorOccurred:
        NSLog("ErrorOccurred")
        break
    case NSStreamEvent.EndEncountered:
          NSLog("EndEncountered")
        break
    default:
        NSLog("unknown.")
    }
}

这样做是有效的,但我想问你这是否是正确的方式?在这一点上,最佳实践是什么?

更新 几周前我又重新研究了一下,发现了我的错误。所以这里是可以工作的代码。

func stream(aStream: NSStream, handleEvent eventCode: NSStreamEvent) {
        switch (eventCode){
    case NSStreamEvent.ErrorOccurred:
        NSLog("ErrorOccurred")
        break
    case NSStreamEvent.EndEncountered:
        NSLog("EndEncountered")
        break
    case NSStreamEvent.None:
        NSLog("None")
        break
    case NSStreamEvent.HasBytesAvailable:
        NSLog("HasBytesAvaible")
        var buffer = [UInt8](count: 4096, repeatedValue: 0)
        if ( aStream == inputstream){

            while (inputstream.hasBytesAvailable){
                var len = inputstream.read(&buffer, maxLength: buffer.count) 
                if(len > 0){
                    var output = NSString(bytes: &buffer, length: buffer.count, encoding: NSUTF8StringEncoding) 
                    if (output != ""){
                        NSLog("server said: %@", output!)
                    }
                }
            } 
        }
        break
    case NSStreamEvent.allZeros:
        NSLog("allZeros")
        break
    case NSStreamEvent.OpenCompleted:
        NSLog("OpenCompleted")
        break
    case NSStreamEvent.HasSpaceAvailable:
        NSLog("HasSpaceAvailable")
        break
  }

嗨,这个解决方案可以同时处理多个响应吗? - Shrikant K
以上代码是用于接收消息,而不是用于响应消息的。有一些框架可以用于使用套接字发送和响应消息,也许可以看一下 socket.io http://socket.io/blog/socket-io-on-ios/。 - hoedding
是的,它是用来接收信息的,但我想问你,如果我同时从服务器收到多个响应,它会处理吗? - Shrikant K
2个回答

3

我正在使用hoedding编写的代码,发现有一个错误。出错的那一行是:

var output = NSString(bytes: &buffer, length: buffer.count, encoding: NSUTF8StringEncoding)

应该被替换为:

var output = NSString(bytes: &buffer, length: len, encoding: NSUTF8StringEncoding)

在获取服务器返回的字节数时,你需要只将其放入output变量中,而不是整个缓冲区的长度,否则你会收到之前请求的垃圾信息。


3
您缺少事件 hasSpaceAvailable,我认为它发生在提示“未知”时。它告诉您它已准备好接收更多数据。
通常情况下,我避免在枚举的 switch 语句中使用 default,因为编译器会告诉您是否有遗漏。

我几周前就想通了。我会在这里接受你的答案,因为你是正确的。这是我的错误。 - hoedding
很高兴你解决了这个问题 - 我回答后才意识到你提问的日期! - Alex
@Alexander,这个解决方案可以同时处理多个响应吗?(在UPDATE中) - Shrikant K
@K.Shrikant 如果您创建一个新的问题,我认为您会得到更好的答案。 - Alex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接