Same way we have created UDPListerner class.
import Foundation
import Network
protocol UDPServerDelegate {
func dataToController(dic: [String : Any])
}
enum ListnerState {
case started
case stoped
case settingUp
}
class UDPServer {
var udpDelegate: UDPServerDelegate?
var dataToTransferViaSocket : [Data]?
var listner : NWListener?
var isConnected : Bool = false
var connection : NWConnection?
var queue = DispatchQueue.global(qos: .userInteractive)
var listnerState: ListnerState = .stoped
static let sharedInstance: UDPServer = {
let instance = UDPServer()
return instance
}()
fileprivate func setupListnerName(_ name: String) {
if let iphoneName = (UserDefaults.standard.object(forKey: "iPhoneName") as? String){
if name != iphoneName{
UserDefaults.standard.set(name, forKey: "iPhoneName")
if !self.isConnected{
}
}
}else{
UserDefaults.standard.set(name, forKey: "iPhoneName")
if !self.isConnected{
}
}
}
func setupListner(delegate : UDPServerDelegate){
isConnected = false
listnerState = .settingUp
udpDelegate = delegate
// Create The Listner
if let port = NWEndpoint.Port(rawValue: 55000){
listner = try! NWListener(using: .udp, on: port)
}else{
let udpOption = NWProtocolUDP.Options()
let params = NWParameters(dtls: nil, udp: udpOption)
params.includePeerToPeer = true
listner = try! NWListener(using: params)
}
// Setup the listnerwith the service
listner?.service = NWListener.Service(name: "MinderService",type: "_camera._udp",domain: "local")
listner?.parameters.includePeerToPeer = true
listner?.parameters.allowLocalEndpointReuse = true
listner?.parameters.acceptLocalOnly = true
// Handle Incoming sonnections
listner?.newConnectionHandler = { (newConnection) in
print("newConnectionHandler")
self.connection = newConnection
self.isConnected = false
self.sendConnectionACK()
newConnection.start(queue: .main)
self.receiveUDP()
}
// Handle listner state changes
listner?.stateUpdateHandler = { [weak self] (newState) in
switch (newState){
case .setup:
print("stateUpdateHandler setup")
case .waiting(let error):
print("stateUpdateHandler error \(error)")
case .cancelled:
print("stateUpdateHandler cancelled")
case .ready:
print("Listning on Port \(String(describing: self?.listner?.port))")
case .failed(let error):
print("stateUpdateHandler Failed: \(error)")
default:
print("stateUpdateHandler default")
return
}
print("Listner State: \(self?.listnerState)")
}
}
func stopListner(){
stopConnection()
listner?.cancel()
listner = nil
listnerState = .stoped
print("Stoped Listner")
}
func stopConnection(){
connection?.cancel()
self.isConnected = false
connection = nil
}
func startListner(){
listner?.start(queue: queue)
listnerState = .started
print("Started Listner")
}
// Receive packets from other side
fileprivate func sendConnectionACK() {
do{
let connectionData = ["Connected":true] as [String : Any]
let dataExample: Data = try NSKeyedArchiver.archivedData(withRootObject: connectionData, requiringSecureCoding: false)
if ((self.connection?.send(content: dataExample, completion: .idempotent)) != nil){
self.isConnected = true
}
}catch let error{
print(error)
}
}
func sendDataViaSocket() {
if self.dataToTransferViaSocket != nil && self.dataToTransferViaSocket?.count != 0{
self.connection?.send(content: self.dataToTransferViaSocket?.first, completion: .idempotent)
self.dataToTransferViaSocket?.removeFirst()
if self.dataToTransferViaSocket != nil && self.dataToTransferViaSocket?.count != 0{
sendDataViaSocket()
}
}
else{
return
}
}
func receiveUDP() {
self.connection?.receiveMessage { (data, context, isComplete, error) in
if data != nil{
let dictionary: Dictionary? = NSKeyedUnarchiver.unarchiveObject(with: data!) as? [String : Any]
if dictionary != nil{
if dictionary!["Disconnected"] != nil{
// self.stopConnection()
}else{
self.udpDelegate?.dataToController(dic: dictionary!)
}
}
}
self.receiveUDP()
}
}
}
```
Above code working perfectly fine with iOS 13 and watch OS 6 , But not working in IOS 14 beta and Watch 7 Beta.
We are getting error as dataSend Extension[562:369291] [connection] nwendpointflowattachprotocols [C1.1
fd74:6572:6d6e:7573:d:8ea4:c65a:3cd3.62742 in_progress socket-flow (satisfied (Path is satisfied), interface: ipsec2, scoped, ipv4,
ipv6)] Failed to attach socket protocol We have taken following measures as suggested in WWDC2020 video on changes in privacy settings
WWDC2020 video - https://developer.apple.com/videos/play/wwdc2020/10110
Added Privacy - Local Network Usage Description in info plist
Bonjour Services -> in array added the Service as camera.udp in info plist
Please let us know if we are missing something .