Post

Replies

Boosts

Views

Activity

Not getting UDP broadcast responses
I'm attempting to build an app the broadcasts on the local network and awaits responses to those broadcast requests. However, the app does not receive the responses. Essentially, the app broadcasts "DISCOVER:1000" to 10.11.21.255, and expects "ADDRESS:10.11.21.100", but never receives it. I built a test client in python, and it works as expected. Running tcpdump on the server shows the response being sent by the server. It just never reaches the ios app. In case it matters, I have the multicast entitlement for the app and local network enabled in Info.plist. import Foundation import Network class UDPClient: ObservableObject { private var connection: NWConnection? private let networkQueue = DispatchQueue(label: "com.example.udp") @Published var isReady = false private var isListening = false func connect() { let host = "10.11.21.255" let port = UInt16(12345) let endpoint = NWEndpoint.hostPort(host: NWEndpoint.Host(host), port: NWEndpoint.Port(integerLiteral: port)) connection = NWConnection(to: endpoint, using: .udp) connection?.stateUpdateHandler = { [weak self] state in switch state { case .ready: self?.networkQueue.async { print("Connection ready") self?.startReceiving() DispatchQueue.main.async { self?.isReady = true } } case .failed(let error): print("Connection failed: \(error)") DispatchQueue.main.async { self?.isReady = false } case .waiting(let error): print("Connection waiting: \(error)") DispatchQueue.main.async { self?.isReady = false } default: DispatchQueue.main.async { self?.isReady = false } break } } connection?.start(queue: networkQueue) } func send() { let message = "DISCOVER:1000" guard let data = message.data(using: .utf8) else { print("Failed to convert message to data") return } guard let connection = self.connection else { return } networkQueue.async { [weak self] in print("Attempting to send message...") guard let self = self else { return } if self.isReady { // Ensure we're listening before sending if !self.isListening { self.startReceiving() // Add a small delay to ensure the receiver is ready self.networkQueue.asyncAfter(deadline: .now() + 0.1) { self.performSend(data: data, connection: connection) } } else { self.performSend(data: data, connection: connection) } } else { print("Connection is not ready. Retrying in 100ms...") self.networkQueue.asyncAfter(deadline: .now() + 0.1) { self.send() } } } } private func performSend(data: Data, connection: NWConnection) { connection.send(content: data, completion: .contentProcessed { error in if let error = error { print("Failed to send: \(error)") } else { print("Send completed successfully") } }) } private func startReceiving() { print("Starting to receive messages...") isListening = true connection?.receiveMessage { [weak self] content, context, isComplete, error in guard let self = self else { return } if let error = error { print("Receive error: \(error)") return } if let data = content { print("Received data: \(data)") if let responseString = String(data: data, encoding: .utf8) { print("Received response: \(responseString)") } else { print("Received data could not be converted to string.") } } else { print("No data received.") } // Continue receiving self.startReceiving() } } func disconnect() { networkQueue.async { [weak self] in self?.connection?.cancel() self?.isListening = false DispatchQueue.main.async { self?.isReady = false } print("Disconnected") } } } My main view: import SwiftUI struct ContentView: View { @StateObject private var udpClient = UDPClient() var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") } .padding() .onAppear() { udpClient.connect() udpClient.send() } } } #Preview { ContentView() }
2
0
176
Dec ’24