swift - 将 NWConnection 用于长时间运行的 TCP 套接字的正确方法
问题描述
我整天都在与 NWConnection 斗争,以便在长时间运行的 TCP 套接字上接收数据。由于缺乏文档,在对自己造成以下错误后,我终于让它工作了:
- 数据不完整(由于只调用receive一次)
- 无序获取 TCP 数据(由于“轮询”从计时器接收......导致多个同时关闭等待获取数据)。
- 遭受无限循环(由于在没有检查“isComplete”布尔值的情况下接收后重新启动接收——一旦套接字从另一端终止,这就是......糟糕......非常糟糕)。
我所学的总结:
- 一旦您处于 .ready 状态,您就可以调用 receive...一次且仅一次
- 收到一些数据后,您可以再次调用接收...但前提是您仍处于 .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()
}
}
}
解决方案
我认为您可以多次使用短时间连接。例如,客户端连接到主机并要求主机做某事,然后告诉主机关闭连接。主机切换到等待模式以准备新的连接。见下图。
当客户端在特定时间内没有向主机发送关闭连接或应答事件时,您应该使用连接计时器来关闭打开的连接。
推荐阅读
- hibernate - 寻找 Hibernate-core 3.5.1-Final 的源代码
- typescript - 如何将十进制值的 RGB 点转换为 HEX 颜色代码以获取 javacript 中的颜色
- python - 与 pyTorch 相比,Jax/Flax(非常)慢的 RNN 前向传递?
- amazon-web-services - 用于 EC2 的 AWS 传出请求 ELB
- angular - 当 [选中] 在 mat 单选按钮中应用时,OnChange 不起作用
- hyperlink - 如何通过pycharm中的内容链接到一行代码?
- flutter - 如何在颤动中点击翻转按钮和旋转按钮时更新视频?
- python - 无法从 javascript 网页中抓取多个相关的下拉列表
- terraform - 如何在 terraform 中将条件资源引用到另一个资源上
- .net - 当我计划在带有 AKS 的 Windows 容器中运行控制台应用程序时,是否需要下载整个 .NET Framework 运行时映像?