对长时间运行的TCP套接字使用NWConnection的正确方法

时间:2019-03-04 04:12:10

标签: swift networking

我一直在与NWConnection进行争斗,以整日在长时间运行的TCP套接字上接收数据。由于缺少文档,我在自己身上犯了以下错误之后,我终于使它工作了:

  1. 数据不完整(由于仅呼叫一次接收)
  2. 无序获取TCP数据(由于从计时器接收“轮询” ...导致多个同时关闭以等待获取数据)。
  3. 遭受无限循环(由于在不检查“ isComplete” Bool的情况下在接收后重新启动接收-一旦套接字从另一端终止,这是...很糟糕...非常糟糕)。

我所学的摘要:

  1. 一旦您处于.ready状态,您就可以呼叫接收...一次,并且只能一次
  2. 一旦收到一些数据,就可以再次调用receive ...,但前提是您仍处于.ready状态且isComplete为false。

这是我的代码。我认为这是对的。但是,如果有错,请告诉我:

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

1 个答案:

答案 0 :(得分:0)

我认为您可以多次使用短时间连接。例如,客户端连接到主机,并要求主机执行某项操作,然后告诉主机关闭连接。主机切换到等待模式以准备新的连接。请参见下图。

当客户端在特定时间内未向主机发送关闭连接或应答事件时,您应该具有连接计时器以关闭打开的连接。