Правильный способ использования NWConnection для долго работающего сокета TCP - PullRequest
0 голосов
/ 04 марта 2019

Я боролся с NWConnection, чтобы весь день получать данные по давно работающему TCP-сокету.Я наконец-то заработал после того, как вызвал у себя следующие ошибки из-за отсутствия документации:

  1. Неполные данные (из-за того, что только один вызов получил)
  2. Получение данных TCPof-order (из-за «опроса» приема от таймера ... что приводит к нескольким одновременным замыканиям, ожидающим получения данных).
  3. Страдает бесконечными циклами (из-за перезапуска приема после получения без проверки "isComplete" Bool- как только сокет завершается с другого конца, это .... плохо ... очень плохо).

Краткое изложение того, что я узнал:

  1. Когда вы находитесь в состоянии .ready, вы можете звонить на получение ... один раз и только один раз
  2. Как только вы получаете некоторые данные, вы можете позвонить на получение снова ... но только если вы все еще находитесь в .readyсостояние и isComplete ложно.

Вот мой код.Я думаю, что это правильно.Но если это не так, пожалуйста, дайте мне знать:

    queue = DispatchQueue(label: "hostname", attributes: .concurrent)
    let serverEndpoint = NWEndpoint.Host(hostname)
    guard let portEndpoint = NWEndpoint.Port(rawValue: port) else { return nil }
    connection = NWConnection(host: serverEndpoint, port: portEndpoint, using: .tcp)
    connection.stateUpdateHandler = { [weak self] (newState) in
        switch newState {
        case .ready:
            debugPrint("TcpReader.ready to send")
            self?.receive()
        case .failed(let error):
            debugPrint("TcpReader.client failed with error \(error)")
        case .setup:
            debugPrint("TcpReader.setup")
        case .waiting(_):
            debugPrint("TcpReader.waiting")
        case .preparing:
            debugPrint("TcpReader.preparing")
        case .cancelled:
            debugPrint("TcpReader.cancelled")
        }
    }

func receive() {  
    connection.receive(minimumIncompleteLength: 1, maximumLength: 8192) { (content, context, isComplete, error) in
        debugPrint("\(Date()) TcpReader: got a message \(String(describing: content?.count)) bytes")
        if let content = content {
            self.delegate.gotData(data: content, from: self.hostname, port: self.port)
        }
        if self.connection.state == .ready && isComplete == false {
            self.receive()
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...