Используйте NSOutputstream и NSInputstream для записи и чтения каждого интервала

Я пытаюсь использовать NSOutputstream и NSInputstream для записи и чтения каждый интервал, скажем, 5 секунд. Это для связи с C# программой на окнах в стиле P2P.

Я хочу использовать NSOutputstream для отправки программы на C# каждые 5 секунд, а затем NSInputstream будет читать ответ от программы на C#.

В настоящее время у меня есть:

class Connection : NSObject, NSStreamDelegate {
var serverAddress: CFString
let serverPort: UInt32 = 11000

private var inputStream: NSInputStream!
private var outputStream: NSOutputStream!

init(serverAddress: CFString) {
    self.serverAddress = serverAddress
}

func connect() {
    print("connecting...")

    var readStream:  Unmanaged<CFReadStream>?
    var writeStream: Unmanaged<CFWriteStream>?

    CFStreamCreatePairWithSocketToHost(nil, self.serverAddress, self.serverPort, &readStream, &writeStream)

    self.inputStream = readStream!.takeRetainedValue()
    self.outputStream = writeStream!.takeRetainedValue()

    self.inputStream.delegate = self
    self.outputStream.delegate = self

    self.inputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
    self.outputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)

    self.inputStream.open()
    self.outputStream.open()

    print("connected...")
}

func disconnect() {
    self.inputStream.close()
    self.outputStream.close()
}

func receive() -> String {
    let data: NSData = "GiveMeCurrentTime".dataUsingEncoding(NSUTF8StringEncoding)!

    let bytesWritten = outputStream.write(UnsafePointer<UInt8>(data.bytes), maxLength: data.length)

    print("wrote \(bytesWritten) bytes")

    var buffer = [UInt8](count: 100, repeatedValue: 0)
    inputStream.read(&buffer,maxLength: buffer.count)

    let currentTime = String.fromCString(UnsafePointer(buffer))
    print("Data received is \(currentTime)")


    return currentTime
}

func stream(stream: NSStream, handleEvent eventCode: NSStreamEvent) {
    //print("stream event")

    if stream === inputStream {
        switch eventCode {
        case NSStreamEvent.ErrorOccurred:
            print("input: ErrorOccurred: \(stream.streamError?.description)")
        case NSStreamEvent.OpenCompleted:
            print("input: OpenCompleted")
        case NSStreamEvent.HasBytesAvailable:
            print("input: HasBytesAvailable")
            break;
        case NSStreamEvent.HasSpaceAvailable:
            break;
        default:
            print("\(eventCode)")
            break
        }
    }
    else if stream === outputStream {
        switch eventCode {
        case NSStreamEvent.ErrorOccurred:
            print("output: ErrorOccurred: \(stream.streamError?.description)")
        case NSStreamEvent.OpenCompleted:
            print("output: OpenCompleted")
        case NSStreamEvent.HasSpaceAvailable:
            print("output: HasSpaceAvailable")
            // Here you can write() to `outputStream`
            break;
        default:
            print("\(eventCode)")
            break
        }
    }
}

Класс соединения будет использоваться, как показано ниже, с NSTimer и NSRunLoop:

func start(ipAddress ipAddress: String) {
        self.conn = Connection(serverAddress: ipAddress)
        self.conn!.connect()
        self.sendTimer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "getTimeAndUpdateUI", userInfo: nil, repeats: true)
        NSRunLoop.currentRunLoop().addTimer(self.sendTimer!, forMode: NSDefaultRunLoopMode)
    }
}

func getTimeAndUpdateUI() {
    let time = self.conn!.receive()
    self.timeLabel.text = "Current time is \(time)"
}

Первый запуск всегда в порядке - я могу узнать текущее время и правильно его отобразить. Но последующие прогоны никогда не удавались. Выходной поток не может записать ни одного байта. И входной поток получил следующую ошибку при чтении:

Произошла ошибка: Необязательно ("Ошибка домена =NSPOSIXErrorDomain Code=32 \" Сломанный канал \"")

Я долго пытался искать, но не смог найти решение. Любая помощь приветствуется.

1 ответ

Решение

Похоже, NSInputStream и NSOutputStream не должны использоваться повторно после завершения потока. Я исправил проблему, изменив код ниже:

func start(ipAddress ipAddress: String) {
        self.conn = Connection(serverAddress: ipAddress)
        self.sendTimer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "getTimeAndUpdateUI", userInfo: nil, repeats: true)
        NSRunLoop.currentRunLoop().addTimer(self.sendTimer!, forMode: NSDefaultRunLoopMode)
}

func getTimeAndUpdateUI() {
    self.conn!.connect()
    let time = self.conn!.receive()
    self.timeLabel.text = "Current time is \(time)"
    self.conn!.disconnect()
}

Каждый раз, когда iOS запрашивает информацию у сервера, она воссоздает экземпляр NSInputStream и NSOutputStream.

Любое предложение по улучшению приветствуется. Благодарю.

Другие вопросы по тегам