• 请不要在回答技术问题时复制粘贴 AI 生成的内容
Trinity888
V2EX  ›  程序员

UDP 包丢包情况严重的问题,请大家帮忙分析一下可能的原因?

  •  
  •   Trinity888 · Jul 2, 2021 · 3344 views
    This topic created in 1798 days ago, the information mentioned may be changed or developed.

    现状: 有个网关设备,自身带一个 wifi,名为 XXXX ;

    APP ( IOS 端)添加这个网关设备配网时,会通过 UDP 广播方式发出去一个数据包,端口固定。

    使用 Window 的 UDP 工具测试时,发现收到包的概率特别大。但是使用 APP 程序( CocoaAsyncSocket 实现),但是收到包的概率太小了,好多包都丢了。

    可能是什么情况?请大家帮忙分析一下,小弟感谢万分!

    相关代码如下:

    import SystemConfiguration.CaptiveNetwork import NetworkExtension

    import UIKit

    class UDPSocketManager: NSObject, GCDAsyncUdpSocketDelegate {

    static var shared = UDPSocketManager()
    
    var udpSocket: GCDAsyncUdpSocket?
    var udpError: String?
    var port = 26600
    
    var isStarting: Bool = false
    
    override init() {
        super.init()
    }
    
    func start() {
        if isStarting {
            return
        }
        self.udpSocket = GCDAsyncUdpSocket(delegate: self, delegateQueue: DispatchQueue.main)
        do {
            try udpSocket?.bind(toPort: UInt16(port), interface: udpError)
            try udpSocket?.enableBroadcast(true)
            try udpSocket?.beginReceiving()
            self.isStarting = true
        } catch {
            print("catch:\(String(describing: error))")
            self.isStarting = false
        }
    }
    
    func close() {
        self.isStarting = false
        udpSocket?.close()
    }
    
    func sendUdp(aaa: String, ssid: String, pw: String, address: Data) {
        let str = "ssid:\(ssid)pw:\(pw)"
        let asciiArr = str.asciiHexValues
        let instructStr = BasicProtocol.gatewayInstructionGeneration(frameNumStrArr: BasicProtocol.gatewayFrameNumStrArr, respFlagStrArr: ["80"], cmdIdStrArr: ["08", "01"], dataStrArr: asciiArr)
        HUD.showSuccess("收到数据:\(aaa)\n 发送数据:\(instructStr)", delay: 5)
        // self.udpSocket.send(Data(instructStr.components(separatedBy: " ").joined().changeToBytes()), toHost: "192.168.4.1", port: UInt16(self.port), withTimeout: -1, tag: 0)
    
        self.udpSocket?.send(Data(instructStr.components(separatedBy: " ").joined().changeToBytes()), toAddress: address, withTimeout: -1, tag: 0)
        
    }
    
    
    func sendUdp(str: String, address: Data) {
        let asciiArr = str.asciiValues
        let instructStr = BasicProtocol.gatewayInstructionGeneration(frameNumStrArr: BasicProtocol.gatewayFrameNumStrArr, respFlagStrArr: ["80"], cmdIdStrArr: ["08", "01"], dataStrArr: asciiArr)
        HUD.showSuccess("发送数据:\(instructStr)", delay: 5)
        self.udpSocket?.send(Data(instructStr.components(separatedBy: " ").joined().changeToBytes()), toAddress: address, withTimeout: -1, tag: 0)
        
    }
    
    func udpSocket(_ sock: GCDAsyncUdpSocket, didReceive data: Data, fromAddress address: Data, withFilterContext filterContext: Any?) {
        // 接受数据
        let strData = data.map({ String(format: "%02x", $0) }).joined(separator: " ")
        HUD.showSuccess("收到数据:\(strData)", delay: 5)
        
        NotificationCenter.default.post(name: NSNotification.Name("UDPSocketNewMessage"), object: ["strData": strData, "address": address])
    }
    
    func udpSocket(_ sock: GCDAsyncUdpSocket, didSendDataWithTag tag: Int) {
        // 发送数据成功
    }
    

    }

    Supplement 1  ·  Jul 2, 2021
    PS:
    网关自带的这个名为:XXXX 的网络(不能上网),但通过手机可以连接上。
    12 replies    2021-07-02 15:08:06 +08:00
    gulugu
        1
    gulugu  
       Jul 2, 2021
    udp 是会丢包的哦,怎么不使用 tcp 呀?
    ShadowPower
        2
    ShadowPower  
       Jul 2, 2021
    MTU 太小了
    Trinity888
        3
    Trinity888  
    OP
       Jul 2, 2021
    @gulugu 网关上不支持做 Server 端,TCP 、UDP 的 Server 端都不行,系统原因。它只能做 client 端。
    Trinity888
        4
    Trinity888  
    OP
       Jul 2, 2021
    @ShadowPower 这一个数据包总共不超过 50 个字节。 除了这个 MTU,还可能是什么原因? 与网关的网络 wifi 有关吗?这个网关的 wifi 是可以连上,但是它是无网络的。
    qwerrewt
        5
    qwerrewt  
       Jul 2, 2021
    tcpdump 看一下
    zdt3476
        6
    zdt3476  
       Jul 2, 2021
    是不是手机连 wifi 网络不稳定
    NSAgold
        7
    NSAgold  
       Jul 2, 2021 via Android
    看描述像是物联网设备的配网
    没有深入接触过这边,但 github 上应该有一些可以参考的吧 esp8266 esp32 配网之类的项目
    Trinity888
        8
    Trinity888  
    OP
       Jul 2, 2021
    @qwerrewt 有使用 udp 工具测试过,收到包的成功率很大。但换成手机 APP( IOS 端,使用 Swift 开发)时,现象是:网关发了好多包了,才收到。 网关是 UDP 广播( 192.168.1.255 )出去,手机连上网关的网络,接收 UDP 包( Server 端),双方固定同一个端口
    Trinity888
        9
    Trinity888  
    OP
       Jul 2, 2021
    @zdt3476 但是用电脑连接上同一个 wifi 后,就能收到。使用 UDP 工具测试时,ok 。至少丢包率不大。
    95276
        10
    95276  
       Jul 2, 2021
    试试 SwiftNIO
    Henry399
        11
    Henry399  
       Jul 2, 2021
    可能网络拥塞造成的
    dndx
        12
    dndx  
       Jul 2, 2021
    有一个需要注意的问题是在 Wifi 网络下发送广播和多播包都会导致严重的频道速率限制:

    https://wyebot.com/2019/02/13/multicast-broadcast-traffic-worry-part1/

    如果发的包比较多,建议用单播单独发给每个客户端来实现。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5338 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 52ms · UTC 07:31 · PVG 15:31 · LAX 00:31 · JFK 03:31
    ♥ Do have faith in what you're doing.