gpt4 book ai didi

ios - NWNetworking/NWListener如何正确接收UDP广播报文?

转载 作者:行者123 更新时间:2023-12-05 05:01:44 32 4
gpt4 key购买 nike

当通过 UDP 接收直接消息时,我可以正常运行以下代码:


import UIKit
import Network

class ViewController: UIViewController {

var udpListener:NWListener?
var backgroundQueueUdpListener = DispatchQueue(label: "udp-lis.bg.queue", attributes: [])
var backgroundQueueUdpConnection = DispatchQueue(label: "udp-con.bg.queue", attributes: [])

var connections = [NWConnection]()

override func viewDidLoad() {
super.viewDidLoad()

myOnButton(self)
}

@IBAction func myOnButton(_ sender: Any) {

guard self.udpListener == nil else {
print(" 🧨 Already listening. Not starting again")
return
}

do {
self.udpListener = try NWListener(using: .udp, on: 2000)
self.udpListener?.stateUpdateHandler = { (listenerState) in

switch listenerState {
case .setup:
print("Listener: Setup")
case .waiting(let error):
print("Listener: Waiting \(error)")
case .ready:
print("Listener: Ready and listens on port: \(self.udpListener?.port?.debugDescription ?? "-")")
case .failed(let error):
print("Listener: Failed \(error)")
case .cancelled:
print("Listener: Cancelled by myOffButton")
for connection in self.connections {
connection.cancel()
}
self.udpListener = nil
default:
break;
}
}

self.udpListener?.start(queue: backgroundQueueUdpListener)
self.udpListener?.newConnectionHandler = { (incomingUdpConnection) in

print ("💁 New connection \(incomingUdpConnection.debugDescription)")

incomingUdpConnection.stateUpdateHandler = { (udpConnectionState) in
switch udpConnectionState {
case .setup:
print("Connection: setup")
case .waiting(let error):
print("Connection: waiting: \(error)")
case .ready:
print("Connection: ready")
self.connections.append(incomingUdpConnection)
self.processData(incomingUdpConnection)
case .failed(let error):
print("Connection: failed: \(error)")
self.connections.removeAll(where: {incomingUdpConnection === $0})
case .cancelled:
print("Connection: cancelled")
self.connections.removeAll(where: {incomingUdpConnection === $0})
default:
break
}
}

incomingUdpConnection.start(queue: self.backgroundQueueUdpConnection)
}

} catch {
print("🧨")
}

}
@IBAction func myOffButton(_ sender: Any) {
udpListener?.cancel()
}

func processData(_ incomingUdpConnection :NWConnection) {

incomingUdpConnection.receiveMessage(completion: {(data, context, isComplete, error) in

if let data = data, !data.isEmpty {
if let string = String(data: data, encoding: .ascii) {
print ("DATA = \(string)")
}
}

if error == nil {
self.processData(incomingUdpConnection)
}
})

}

}


像这样直接向设备发送无穷无尽的 UDP 包:

echo -n "Testdata" | socat - udp-datagram:192.168.2.126:2000,broadcast,sourceport=2000

按预期工作,所有消息都到达:

Listener: Waiting POSIXErrorCode: Network is down
Listener: Ready and listens on port: 2000
💁 New connection [C1 192.168.2.134:2000 udp, local: 192.168.2.126:2000, indefinite, server, path satisfied (Path is satisfied), interface: en0, scoped, ipv4, ipv6, dns]
Connection: ready
DATA = Testdata
DATA = Testdata
DATA = Testdata
DATA = Testdata
...

但尝试对广播消息进行同样的操作

echo -n "Testat" | socat - udp-datagram:255.255.255.255:2000,broadcast,sourceport=2000

导致仅接收第一条消息,并与每个接收到的 UDP 数据包建立新连接。


Listener: Waiting POSIXErrorCode: Network is down
Listener: Ready and listens on port: 2000
💁 New connection [C1 192.168.2.134:2000 udp, local: 0.0.0.0:2000, indefinite, server, path satisfied (Path is satisfied), interface: en0, ipv4, ipv6, dns]
Connection: ready
DATA = Testdata
2020-06-28 14:22:03.668116+0200 networking[25440:13489733] [] nw_channel_reclassify_input reclassify failed, could not find client for slot 77926755-A281-4AFD-9649-92FBD1A21FA6
💁 New connection [C2 192.168.2.134:2000 udp, local: 0.0.0.0:2000, indefinite, server, path satisfied (Path is satisfied), interface: en0, ipv4, ipv6, dns]
2020-06-28 14:22:04.384443+0200 networking[25440:13489733] [] nw_channel_reclassify_input reclassify failed, could not find client for slot 7EAC98FA-F665-43C1-9B15-B68B74A56BBC
💁 New connection [C3 192.168.2.134:2000 udp, local: 0.0.0.0:2000, indefinite, server, path satisfied (Path is satisfied), interface: en0, ipv4, ipv6, dns]
2020-06-28 14:22:05.096808+0200 networking[25440:13489733] [] nw_channel_reclassify_input reclassify failed, could not find client for slot AA3EE3BA-D891-4D07-87AF-0CB0A9382CDF
💁 New connection [C4 192.168.2.134:2000 udp, local: 0.0.0.0:2000, indefinite, server, path satisfied (Path is satisfied), interface: en0, ipv4, ipv6, dns]
2020-06-28 14:22:05.714651+0200 networking[25440:13489733] [] nw_channel_reclassify_input reclassify failed, could not find client for slot ED108E8B-E9BC-43C3-8AA7-B4BD0515EB54

解决方法是在每次收到数据包后取消连接,但我怀疑这是用于接收 UDP 广播消息的方式。那么死循环接收UDP广播包的正确做法是什么?

最佳答案

好的,我得到了某种答案。

我在 Objective-C 中遇到了同样的基本问题。我采取了取消处理程序中的连接的步骤,这种方法可行,但您最终会丢失数据 - 根据我的经验,大约 30% - 因为流无法获取广播数据。

不过,我确实从 dts 那里得到了反馈,基本上是这样的——网络库不是为接收广播 UDP 而设计的。

我已经恢复到 BSD 套接字。

关于ios - NWNetworking/NWListener如何正确接收UDP广播报文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62622612/

32 4 0
文章推荐: python-3.x - UnexpectedTagNameException : Message: Select only works on