Post

Replies

Boosts

Views

Activity

Reply to How to initialize NWUDPSession to listen on a given port?
I’m building an app with this goal: I have a continuous stream of UDP datagrams coming in but NWListener stops listening as soon as it generates a NWConnection and doesn’t start listening again until the connection was cancelled and the listener restarted, which is all extremely time consuming and causes about 1/3 of the datagrams to be dropped. So I either find a solution through NWUDPSession or else there’s a trick to keep NWListener actively listening at all times in which case I’m all ears.
Mar ’23
Reply to How to initialize NWUDPSession to listen on a given port?
Here’s the code that drops a huge amount of datagrams. I have also tried with queue .main with the same results. Using NWConnection.receive or .receiveMessage makes no difference. import Network import SwiftUI class udpCatcher: ObservableObject {          init() {         print("init started.")                  var lastTime = Date() // used to know how much time it took between receiving datagrams, mostly for my use in combination with optional filtering for specific data that can be enabled by un-commenting some code below         var counter = 0 // used to add indentation to better follow the scrolling of the data         let printState = false // if false then only the data will print, if true then also the state of the listener and the connection         let listener = try! NWListener(using: .udp, on: 5000)         listener.newConnectionLimit = NWListener.InfiniteConnectionLimit                  listener.stateUpdateHandler = { state in             if printState {print("listener state: \(listener.state)")}         }                  listener.newConnectionHandler = { connection in                          if printState {print("newConnectionHandler triggered: connection state: \(connection.state), listener state: \(listener.state)")}                          connection.stateUpdateHandler = { newState in                 switch newState {                                      case .ready:                                          if printState {print("Connection state: \(connection.state), listener state: \(listener.state)")}                                          connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { (data, context, isComplete, error) in                         if let data = data, !data.isEmpty {                             var message = String(decoding: data, as: UTF8.self)                              //                            if message.hasPrefix("$XXXX") { // for optional filtering of messages                                 counter += 1                                 if counter % 5 == 0 { // indentation every 5th line to better follow the scrolling                                     print("\(counter) Received data:     \(message)   \((Date().timeIntervalSince(lastTime)*100).rounded()/100)\"")                                 } else {                                     print("\(counter)     Received data: \(message)   \((Date().timeIntervalSince(lastTime)*100).rounded()/100)\"")                                 }                                 lastTime = Date() //                            }                             // Process the data here                          }                                                  if let error = error {                             if printState {print("Connection error: \(error)")}                         }                                                  if isComplete {                             connection.cancel()                             if printState {print("Connection state: \(connection.state), listener state: \(listener.state)")}                         }                     }                                      case let .failed(error):                     if printState {print("Connection failed with error \(error.localizedDescription), listener state: \(listener.state)")}                                      default:                     if printState {print("Connection state: \(connection.state), listener state: \(listener.state)")}                                      }             }                          connection.start(queue: .global(qos: .userInteractive))         }                  listener.start(queue: .global(qos: .userInteractive))     } }
Mar ’23
Reply to How to initialize NWUDPSession to listen on a given port?
All the adresses and ports are identical between datagrams. Regarding BSD, could you please help me on my way? This isn’t built into Playgrounds and not part of its documentation either. Can you give me links to files, documentation, and code snippets and can you tell me how to import it into Playgrounds on iPad? That would save me hours, if not days, and would be mightily appreciated! Thanks.
Mar ’23
Reply to How to initialize NWUDPSession to listen on a given port?
It’s broadcast. I’d love to stick with Network but as far as I can tell as a beginning Swift developer, it’s broken. newConnectionHandler won’t be triggered until the current connection is closed therefore dropping all the datagrams in the interval. Unless you have a fix for that through threads or whatever, there’s going to be no way around it. I’ve already tried different threads in the queues of the listener and connection to no avail. I haven’t found any working sample code on the internet. I’m stumped. What I did find is complaints about datagrams being dropped going back 3 years, with no solution offered. But realistically, I expect I’m going to have to go the BSD route, or find yet another alternative. I did discover Darwin in the mean time and managed to start a UDP connection and receive the first few bytes. But it’s a hard slog without guidance. Trying infinite combinations of possible syntax in the hope of making it work is not fun. I really do need sample code if you can spare some. Is your BSD solution the same as going through Darwin or is it another alley?
Mar ’23