Swift Udp Connection

How to work with UDP sockets in iOS, swift?

This solution work for me! Thanks @Paulw11

Swift 4, XCode 10.1, iOS 12.0

Simple connect to the public UDP server (This is NOT optimal version but works):

import UIKit
import Network

class ViewController: UIViewController {

var connection: NWConnection?
var hostUDP: NWEndpoint.Host = "iperf.volia.net"
var portUDP: NWEndpoint.Port = 5201

override func viewDidLoad() {
super.viewDidLoad()

// Hack to wait until everything is set up
var x = 0
while(x<1000000000) {
x+=1
}
connectToUDP(hostUDP,portUDP)
}

func connectToUDP(_ hostUDP: NWEndpoint.Host, _ portUDP: NWEndpoint.Port) {
// Transmited message:
let messageToUDP = "Test message"

self.connection = NWConnection(host: hostUDP, port: portUDP, using: .udp)

self.connection?.stateUpdateHandler = { (newState) in
print("This is stateUpdateHandler:")
switch (newState) {
case .ready:
print("State: Ready\n")
self.sendUDP(messageToUDP)
self.receiveUDP()
case .setup:
print("State: Setup\n")
case .cancelled:
print("State: Cancelled\n")
case .preparing:
print("State: Preparing\n")
default:
print("ERROR! State not defined!\n")
}
}

self.connection?.start(queue: .global())
}

func sendUDP(_ content: Data) {
self.connection?.send(content: content, completion: NWConnection.SendCompletion.contentProcessed(({ (NWError) in
if (NWError == nil) {
print("Data was sent to UDP")
} else {
print("ERROR! Error when data (Type: Data) sending. NWError: \n \(NWError!)")
}
})))
}

func sendUDP(_ content: String) {
let contentToSendUDP = content.data(using: String.Encoding.utf8)
self.connection?.send(content: contentToSendUDP, completion: NWConnection.SendCompletion.contentProcessed(({ (NWError) in
if (NWError == nil) {
print("Data was sent to UDP")
} else {
print("ERROR! Error when data (Type: Data) sending. NWError: \n \(NWError!)")
}
})))
}

func receiveUDP() {
self.connection?.receiveMessage { (data, context, isComplete, error) in
if (isComplete) {
print("Receive is complete")
if (data != nil) {
let backToString = String(decoding: data!, as: UTF8.self)
print("Received message: \(backToString)")
} else {
print("Data == nil")
}
}
}
}
}

Swift UDP Connection Issue

In your function receive you are using the NWConnection.receiveMessage if you check the documentation here:

https://developer.apple.com/documentation/network/nwconnection/3020638-receivemessage

You'll see that it schedules a single receive completion handler. That means that you'll have to do something to trigger it again. What I normally do is have a function like:

private func setupReceive() {
connection.receive(minimumIncompleteLength: 1, maximumLength: MTU) { (data, _, isComplete, error) in
if let data = data, !data.isEmpty {
let message = String(data: data, encoding: .utf8)
print("connection \(self.id) did receive, data: \(data as NSData) string: \(message ?? "-")")
self.send(data: data)
}
if isComplete {
self.connectionDidEnd()
} else if let error = error {
self.connectionDidFail(error: error)
} else {
self.setupReceive() // HERE I SET THE RECEIVE AGAIN
}
}
}

That way, after processing the read, you end up setting up another single receive completion handler.

If you want to see a full example, you can check my article on using Network.framework here:

https://rderik.com/blog/building-a-server-client-aplication-using-apple-s-network-framework/

The example uses TCP instead of UDP, but it should give a general idea.

UDP Listener on iOS 14

I was able to explore this some more and got some help via the apple developer forums, posting an answer here as well for those who are interested.

I ended up using an NWListener to listen for UDP packets, then set up an NWConnection once once I'd received something. I use this NWConnection to read data from the UDP broadcast.

From Quinn "The Eskimo:"

Listening for UDP broadcasts via an NWListener and then using the NWConnection objects it vends (via the new connection handler) to communicate over unicast with the broadcast’s sender is an expected use case.

I encourage anyone reading this to check out our discussion on the Apple Developer Forum as well.

Here is my implementation:

  var udpListener: NWListener?
var udpConnection: NWConnection?
var backgroundQueueUdpListener = DispatchQueue.main

func findUDP() {
let params = NWParameters.udp
udpListener = try? NWListener(using: params, on: 15000)

udpListener?.service = NWListener.Service.init(type: "_appname._udp")

self.udpListener?.stateUpdateHandler = { update in
print("update")
print(update)
switch update {
case .failed:
print("failed")
default:
print("default update")
}
}
self.udpListener?.newConnectionHandler = { connection in
print("connection")
print(connection)
self.createConnection(connection: connection)
self.udpListener?.cancel()
}
udpListener?.start(queue: self.backgroundQueueUdpListener)
}

func createConnection(connection: NWConnection) {
self.udpConnection = connection
self.udpConnection?.stateUpdateHandler = { (newState) in
switch (newState) {
case .ready:
print("ready")
self.send()
self.receive()
case .setup:
print("setup")
case .cancelled:
print("cancelled")
case .preparing:
print("Preparing")
default:
print("waiting or failed")
}
}
self.udpConnection?.start(queue: .global())
}

func endConnection() {
self.udpConnection?.cancel()
}

Swift and UDP socket packet send twice

For everyone is interested, this issue is caused by the network. At home I've a Vodafone network, with their router (Vodafone Station Revolution). The Vodafone Station Revolution generate Wi-Fi @ 2,4GHz and Wi-Fi @ 5GHz. When I try to send an UDP packet on this network this packet will posted twice one for the 2,4GHz and one for the 5GHz network. So to solve my issue I disabled the 5GHz network and all work fine. It is not a code problem, indeed it's a network problem.
I hope my experience will be useful for other person who need the send UDP packet on Vodafone network.
By the way thank you for help.

UDP Connection failed - Error No route to host since the new iOS Update 14.5.1

I found out you have to request the Multicast Networking Entitlement from Apple:
https://developer.apple.com/contact/request/networking-multicast

Since iOS 14.5 you have to request to use UDP...

If they give you the permission to use it, just follow these steps explained here:
https://developer.apple.com/forums/thread/663271

They usually answer after 1-2 days.



Related Topics



Leave a reply



Submit