web-dev-qa-db-fra.com

Swift: recevez UDP avec GCDAsyncUdpSocket

CONTEXTE:

Je veux pouvoir envoyer et recevoir des paquets UDP entre mon application iOS et un serveur. Le serveur renvoie tous les messages entrants au client de l'application. Le serveur est testé et confirmé fonctionne. J'ai un StartViewController qui démarre deux classes qui implémentent GCDAsyncUdpSocketDelegate, une pour l'envoi et une pour la réception. Le "socket d'envoi" fonctionne, le serveur reçoit les messages.

PROBLÈME:

L'application ne récupère jamais le message entrant après son envoi. Quelque chose avec la configuration du socket d'écoute est probablement faux car didReceiveData n'est jamais appelé.

Ai-je fait ça complètement mal?

Début:

class StartViewController: UIViewController {

   var inSocket : InSocket!
   var outSocket : OutSocket!

   override func viewDidLoad() {
       super.viewDidLoad()
       inSocket = InSocket()
       outSocket = OutSocket()
   }

   @IBAction func goButton(sender: UIButton) {
       outSocket.send("This is a message!")
   }
}

Recevoir:

class InSocket: NSObject, GCDAsyncUdpSocketDelegate {

   let IP = "255.255.255.255"
   let PORT:UInt16 = 5556
   var socket:GCDAsyncUdpSocket!

   override init(){
       super.init()
       setupConnection()
   }

   func setupConnection(){
       var error : NSError?
       socket = GCDAsyncUdpSocket(delegate: self, delegateQueue: dispatch_get_main_queue())
       socket.bindToPort(PORT, error: &error)
       socket.enableBroadcast(true, error: &error)
       socket.joinMulticastGroup(IP, error: &error)
       socket.beginReceiving(&error)
   }

   func udpSocket(sock: GCDAsyncUdpSocket!, didReceiveData data: NSData!, fromAddress address: NSData!,      withFilterContext filterContext: AnyObject!) {
       println("incoming message: \(data)");
   }
}

Envoyer:

class OutSocket: NSObject, GCDAsyncUdpSocketDelegate {

   let IP = "90.112.76.180"
   let PORT:UInt16 = 5556
   var socket:GCDAsyncUdpSocket!

   override init(){
       super.init()
       setupConnection()
   }

   func setupConnection(){
       var error : NSError?
       socket = GCDAsyncUdpSocket(delegate: self, delegateQueue: dispatch_get_main_queue())
       socket.connectToHost(IP, onPort: PORT, error: &error)
   }

   func send(message:String){
       let data = message.dataUsingEncoding(NSUTF8StringEncoding)
       socket.sendData(data, withTimeout: 2, tag: 0)
   }

   func udpSocket(sock: GCDAsyncUdpSocket!, didConnectToAddress address: NSData!) {
       println("didConnectToAddress");
   }

   func udpSocket(sock: GCDAsyncUdpSocket!, didNotConnect error: NSError!) {
       println("didNotConnect \(error)")
   }

   func udpSocket(sock: GCDAsyncUdpSocket!, didSendDataWithTag tag: Int) {
       println("didSendDataWithTag")
   } 

   func udpSocket(sock: GCDAsyncUdpSocket!, didNotSendDataWithTag tag: Int, dueToError error: NSError!) {
        println("didNotSendDataWithTag")
   }
}

Edit: Ajout d'une ligne de code oubliée.

18
rilar

Je l'ai finalement fait fonctionner avec cette configuration de socket:

func setupConnection(){
    var error : NSError?
    socket = GCDAsyncUdpSocket(delegate: self, delegateQueue: dispatch_get_main_queue())
    socket.bindToPort(PORT, error: &error)
    socket.connectToHost(SERVER_IP, onPort: PORT, error: &error)
    socket.beginReceiving(&error)
    send("ping")
}

func send(message:String){
   let data = message.dataUsingEncoding(NSUTF8StringEncoding)
   socket.sendData(data, withTimeout: 2, tag: 0)
}
12
rilar

Apple Swift version 4.2.1 Exemple UDP bien testé: -

ÉTAPE 1 :- pod 'CocoaAsyncSocket'

ÉTAPE 2 :- import CocoaAsyncSocket dans votre UIViewController.

ÉTAPE 3: - UIViewController

        import UIKit
import CocoaAsyncSocket

class ViewController: UIViewController {
    @IBOutlet weak var btnOnOff: LightButton!
    @IBOutlet weak var lblStatus: UILabel!
    var inSocket : InSocket!
    var outSocket : OutSocket!
    override func viewDidLoad() {
        super.viewDidLoad()
        lblStatus.isHidden = true
        inSocket = InSocket()
        outSocket = OutSocket()
        outSocket.setupConnection {
            self.lblStatus.isHidden = false
        }
    }
    @IBAction func btnLight(_ sender: Any) {
        let signal:Signal = Signal()
        self.outSocket.send(signal: signal)
    }
}

ÉTAPE 4: - ( Prise réceptrice

       //Reciving End...
class InSocket: NSObject, GCDAsyncUdpSocketDelegate {
   //let IP = "10.123.45.2"
    let IP = "127.0.0.1"
    let PORT:UInt16 = 5001
    var socket:GCDAsyncUdpSocket!
    override init(){
        super.init()
        setupConnection()
    }
    func setupConnection(){
        socket = GCDAsyncUdpSocket(delegate: self, delegateQueue:DispatchQueue.main)
        do { try socket.bind(toPort: PORT)} catch { print("")}
        do { try socket.enableBroadcast(true)} catch { print("not able to brad cast")}
        do { try socket.joinMulticastGroup(IP)} catch { print("joinMulticastGroup not procceed")}
        do { try socket.beginReceiving()} catch { print("beginReceiving not procceed")}
    }
    //MARK:-GCDAsyncUdpSocketDelegate
    func udpSocket(_ sock: GCDAsyncUdpSocket, didReceive data: Data, fromAddress address: Data, withFilterContext filterContext: Any?) {
          print("incoming message: \(data)");
          let signal:Signal = Signal.unarchive(d: data)
          print("signal information : \n first \(signal.firstSignal) , second \(signal.secondSignal) \n third \(signal.thirdSignal) , fourth \(signal.fourthSignal)")

    }
    func udpSocket(_ sock: GCDAsyncUdpSocket, didNotConnect error: Error?) {
    }

    func udpSocketDidClose(_ sock: GCDAsyncUdpSocket, withError error: Error?) {
    }
}

ÉTAPE 5: - ( Envoi du socket ..

//Sending End...
class OutSocket: NSObject, GCDAsyncUdpSocketDelegate {
    // let IP = "10.123.45.1"
    let IP = "127.0.0.1"
    let PORT:UInt16 = 5001
    var socket:GCDAsyncUdpSocket!
    override init(){
        super.init()

    }
    func setupConnection(success:(()->())){
        socket = GCDAsyncUdpSocket(delegate: self, delegateQueue:DispatchQueue.main)
          do { try socket.bind(toPort: PORT)} catch { print("")}
          do { try socket.connect(toHost:IP, onPort: PORT)} catch { print("joinMulticastGroup not procceed")}
          do { try socket.beginReceiving()} catch { print("beginReceiving not procceed")}
        success()
    }
    func send(signal:Signal){
        let signalData = Signal.archive(w: signal)
        socket.send(signalData, withTimeout: 2, tag: 0)
    }
    //MARK:- GCDAsyncUdpSocketDelegate
    func udpSocket(_ sock: GCDAsyncUdpSocket, didConnectToAddress address: Data) {
        print("didConnectToAddress");
    }
    func udpSocket(_ sock: GCDAsyncUdpSocket, didNotConnect error: Error?) {
        if let _error = error {
            print("didNotConnect \(_error )")
        }
    }
    func udpSocket(_ sock: GCDAsyncUdpSocket, didNotSendDataWithTag tag: Int, dueToError error: Error?) {
          print("didNotSendDataWithTag")
    }
    func udpSocket(_ sock: GCDAsyncUdpSocket, didSendDataWithTag tag: Int) {
        print("didSendDataWithTag")
    }
}

ÉTAPE 6: - Vos Signal Données que vous allez Envoyer/Recevoir

import Foundation
struct Signal {
    var firstSignal:UInt16 = 20
    var secondSignal:UInt16 = 30
    var thirdSignal: UInt16  = 40
    var fourthSignal: UInt16 = 50
    static func archive(w:Signal) -> Data {
        var fw = w
        return Data(bytes: &fw, count: MemoryLayout<Signal>.stride)
    }
    static func unarchive(d:Data) -> Signal {
        guard d.count == MemoryLayout<Signal>.stride else {
            fatalError("BOOM!")
        }
        var s:Signal?
        d.withUnsafeBytes({(bytes: UnsafePointer<Signal>)->Void in
            s = UnsafePointer<Signal>(bytes).pointee
        })
        return s!
    }
}
2
Abhimanyu Rathore