V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Trinity888
V2EX  ›  程序员

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

  •  
  •   Trinity888 · 2021-07-02 09:36:37 +08:00 · 2770 次点击
    这是一个创建于 1240 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现状: 有个网关设备,自身带一个 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) {
        // 发送数据成功
    }
    

    }

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

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

    如果发的包比较多,建议用单播单独发给每个客户端来实现。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   968 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 20:23 · PVG 04:23 · LAX 12:23 · JFK 15:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.