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
}
イベントhasSpaceAvailable
がありません。「不明」と表示されたときに発生すると思います。より多くのデータを受信する準備ができていることを示しています。
一般的に、列挙型のswitchステートメントでdefault
を使用することは避けます。何かを逃した場合はコンパイラーが通知するからです。
Hoeddingによって書かれたコードを使用していますが、間違いに気付きました。この線:
var output = NSString(bytes: &buffer, length: buffer.count, encoding: NSUTF8StringEncoding)
次のものに置き換える必要があります:
var output = NSString(bytes: &buffer, length: len, encoding: NSUTF8StringEncoding)
output
varを取得する必要があるのは、サーバーから返された文字数のみであり、バッファーの全長ではありません。そうしないと、以前のリクエストから不要な情報が取得されます。