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_countI'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.
But generally, infinite loop is something you should better avoid. Especially in your case, `loopForever() in your client will send too many UDP packets to be processed by the server in a short period.
Client:
import Foundation
import Network
let ServerName = "OOPer's mini"
class ExampleClient {
lazy var connection: NWConnection = {
let connection = NWConnection(
to: .service(
name: ServerName,
type: "_test._udp",
domain: "local",
interface: nil
),
using: .udp
)
connection.stateUpdateHandler = {newState in
switch newState {
case .ready:
print("connection ready")
self.sendMessage()
case .failed(let error):
print("client failed with error: \(error)")
default:
break
}
}
return connection
}()
func run() {
connection.start(queue: DispatchQueue(label: "client"))
}
func sendMessage() {
connection.send(content: "hello".data(using: .utf8), completion: .contentProcessed({error in
if let error = error {
print("error while sending hello: \(error)")
return
}
print("sending hello succeeded")
self.connection.receiveMessage {data, context, isComplete, error in
if let error = error {
print("error while receiving reply: \(error)")
return
}
print("received:", data.flatMap{String(data: $0, encoding: .utf8)} ?? "undecodable data")
self.sendMessage()
}
}))
}
}
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
print("Accepted:", newConnection)
DispatchQueue.main.async {
self.connections.append(newConnection)
}
newConnection.start(queue: DispatchQueue(label: "new client"))
self.receive(on: newConnection)
}
return listener
}()
func run() {
self.listener.start(queue: DispatchQueue(label: "server"))
}
func receive(on connection: NWConnection) {
connection.receiveMessage {data, context, isComplete, error in
if let error = error {
print(error)
return
}
print("received:", data.flatMap{String(data: $0, encoding: .utf8)} ?? "undecodable data")
connection.send(content: "world".data(using: .utf8), completion: .contentProcessed({error in
if let error = error {
print("error while sending data: \(error)")
return
}
print("sent reply")
self.receive(on: connection)
}))
}
}
}
let server = ExampleServer()
server.run()
RunLoop.main.run()Network framework is not yet documented clearly and I'm not accustomed to use it, so there may be many points to improve.
But this code works steadily for a while...