I'm trying to get a UDP server functioning within Network.framework. However, whenever I managed to get my client and server connected, after some time I receive the error nw_read_request_get_maximum_datagram_count
I've tried looping with Timer and with DispatchQueue, but eventually the server or client crashes with the above error.
Client
import Foundation
import Network
class ExampleClient {
lazy var connection: NWConnection = {
let connection = NWConnection(
to: .service(
name: "Emma’s MacBook Pro",
type: "_test._udp",
domain: "local",
interface: nil
),
using: .udp
)
connection.stateUpdateHandler = { (newState) in
switch newState {
case .ready:
self.loopForever()
case .failed(let error):
print("client failed with error: \(error)")
default:
break
}
}
return connection
}()
func run() {
connection.start(queue: DispatchQueue(label: "client"))
}
func loopForever() {
while true {
connection.send(content: "hello".data(using: .utf8), completion: .contentProcessed({ (error) in
if let error = error {
print("error while sending hello: \(error)")
}
self.connection.receiveMessage { (data, context, isComplete, error) in
return
}
}))
}
}
}
let client = ExampleClient()
client.run()
RunLoop.main.run()
Server
import Foundation
import Network
class ExampleServer {
var connections = [NWConnection]()
lazy var listener: NWListener = {
let listener = try! NWListener(using: .udp)
listener.service = NWListener.Service(type: "_test._udp")
listener.serviceRegistrationUpdateHandler = { (serviceChange) in
switch serviceChange {
case .add(let endpoint):
switch endpoint {
case let .service(name, _, _, _):
print("listening as name \(name)")
default:
break
}
default:
break
}
}
listener.newConnectionHandler = { (newConnection) in
newConnection.start(queue: DispatchQueue(label: "new client"))
self.connections.append(newConnection)
}
return listener
}()
func run() {
self.listener.start(queue: DispatchQueue(label: "server"))
while true {
for connection in self.connections {
connection.receiveMessage { (message, context, isComplete, error) in
connection.send(content: "world".data(using: .utf8), completion: .contentProcessed({ (error) in
if let error = error {
print("error while sending data: \(error)")
}
}))
}
}
}
}
}
let server = ExampleServer()
server.run()
RunLoop.main.run()
I'd like to maintain a constant connection between the server and client until the client or server manually disconnect.
In the receiver, don't queue your receive handler inside your send's completion handler.
In the server, don't try to queue up an infinite number of receive handlers. One at a time per connection is enough.