【问题标题】:How to work with UDP sockets in iOS, swift?如何在 iOS 中快速使用 UDP 套接字?
【发布时间】:2019-07-05 13:31:27
【问题描述】:

我正在尝试连接到本地 esp8266 UDP 服务器。 SwiftSocket 没有文档。 CocoaAsyncSocket 不起作用。 如何连接并发送数据到 udp 服务器?我该怎么办?

我编写了示例 UDP python 服务器并尝试通过 SwiftSocket 和 CocoaAsyncSocket 连接到它们。我没有从应用程序中获得反馈。服务器不接收连接。 例如 - 最多的尝试之一:

    var connection = NWConnection(host: "255.255.255.255", port: 9093, using: .udp)

    connection.stateUpdateHandler = { (newState) in
        switch (newState) {
        case .ready:
            print("ready")
        case .setup:
            print("setup")
        case .cancelled:
            print("cancelled")
        case .preparing:
            print("Preparing")
        default:
            print("waiting or failed")
            break
        }
    }
    connection.start(queue: .global())
    connection.send(content: "Xyu".data(using: String.Encoding.utf8), completion: NWConnection.SendCompletion.contentProcessed(({ (NWError) in
        print(NWError)
    })))
    connection.receiveMessage { (data, context, isComplete, error) in
        print("Got it")
        print(data)
    }

无法连接到服务器

【问题讨论】:

    标签: ios swift sockets udp


    【解决方案1】:

    您需要等到您的连接处于ready 状态后,才能尝试发送或接收任何数据。您还需要在属性中保留对您的连接的强引用,以防止它在函数退出时立即被释放。

    var connection: NWConnection?
    
    func someFunc() {
    
        self.connection = NWConnection(host: "255.255.255.255", port: 9093, using: .udp)
    
        self.connection?.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.connection?.start(queue: .global())
    
    }
    
    func send() {
        self.connection?.send(content: "Test message".data(using: String.Encoding.utf8), completion: NWConnection.SendCompletion.contentProcessed(({ (NWError) in
            print(NWError)
        })))
    }
    
    func receive() {
        self.connection?.receiveMessage { (data, context, isComplete, error) in
            print("Got it")
            print(data)
        }
    }
    

    【讨论】:

    • 感谢您的回答!当我在空项目上运行此代码时(从 viewDidLoad() 运行 someFunction() )我收到此错误:
    • 2019-02-12 22:28:41.553015+0300 Nanopix Pilot[3891:189405] [] nw_socket_service_writes_block_invoke [C1:1] sendmsg(fd 5, 3 bytes) [13: Permission denied]
    • 你正在尝试发送一个广播包;我不确定这是否被允许。最好将数据包发送到您尝试与之通信的特定主机
    • 非常感谢!我成功连接到公共 UDP 服务器。下面我写最终代码
    【解决方案2】:

    这个解决方案对我有用!谢谢 @Paulw11
    Swift 4、XCode 10.1、iOS 12.0
    简单连接到公共 UDP 服务器(这不是最佳版本,但有效):

    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 5.x iOS 13 上工作。发送数据没问题,但我似乎无法让它接收任何东西。我正在尝试使用 python 脚本发送简单的消息。
    • 你救了我的命!最后,我能够打开连接并使用 Swift 5 向服务器发送消息,而无需将我的 macOS 升级到 Catalina!谢谢 ! P.S.:如果你需要使用 TCP 连接,这个例子也适用,只需从 UDP 更改为 TCP。
    • 如何使连接持续监听?
    猜你喜欢
    • 1970-01-01
    • 2012-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-04
    • 2018-04-29
    • 2014-12-14
    • 1970-01-01
    相关资源
    最近更新 更多