web-dev-qa-db-ja.com

SwiftでNSInputStreamからデータを受信する

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()   
}

この部分は機能しています。デリゲートを自分に設定したので、このクラスで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」を出力するはずですが、「不明」と出力しました。毎回。だから私は少し遊んで、これでうまくいきました:

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

このように機能していますが、これが正しい方法かどうかを確認したいと思いますか?この時点でのベストプラクティスは何ですか?

[〜#〜] update [〜#〜]数週間前にもう一度作業して、間違いを見つけました。だからここに作業コードがあります。

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
  }
18
hoedding

イベントhasSpaceAvailableがありません。「不明」と表示されたときに発生すると思います。より多くのデータを受信する準備ができていることを示しています。

一般的に、列挙型のswitchステートメントでdefaultを使用することは避けます。何かを逃した場合はコンパイラーが通知するからです。

3
Alex

Hoeddingによって書かれたコードを使用していますが、間違いに気付きました。この線:

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

次のものに置き換える必要があります:

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

output varを取得する必要があるのは、サーバーから返された文字数のみであり、バッファーの全長ではありません。そうしないと、以前のリクエストから不要な情報が取得されます。

3
Patrick Jollain