You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS Network Framework如何同时接收UDP单播与多播数据

问题根因

你现在的冲突来源于两个独立的Network对象(NWListener和NWMulticastGroup)同时尝试绑定3610端口,默认情况下系统不允许两个socket绑定同一个端口,先启动的NWMulticastGroup占用了端口,后续的NWListener无法正常绑定监听,所以单播数据无法接收。

最优解决方案:仅用NWMulticastGroup同时处理单播+多播

你初始化NWMulticastGroup时已经设置了disableUnicast: false,这个配置本身就支持NWMulticastGroup同时接收两类数据:

  • 发往224.0.23.0:3610的多播数据
  • 发往本地网卡IP:3610的单播数据
    不需要额外启动NWListener监听单播,直接在多播的接收回调里区分数据类型处理即可。

修改后参考代码

import Foundation
import Network

class Controller: ObservableObject {
  @Published var rxContents = String()
  @Published var rxFrom = String()
  
  init() {
    receiveUdp()
  }
  
  func receiveUdp() {
    guard let multicast = try? NWMulticastGroup(for: [ .hostPort(host: "224.0.23.0", port: 3610) ], disableUnicast: false)
    else { fatalError() }
    let group = NWConnectionGroup(with: multicast, using: .udp)
    group.setReceiveHandler(maximumMessageSize: 16384, rejectOversizedMessages: true) { (message, content, isComplete) in
      guard let content = content, let msgStr = String(data: content, encoding: .utf8) else { return }
      let remoteEndpoint = message.remoteEndpoint
      print("收到数据来自: \(String(describing: remoteEndpoint)),内容: \(msgStr)")
      
      // 区分多播/单播数据
      if case .hostPort(let host, _) = remoteEndpoint {
        if host.debugDescription == "224.0.23.0" {
          // 处理多播数据逻辑
          print("这是多播数据")
        } else {
          // 处理单播数据逻辑
          self.rxFrom = String(describing: remoteEndpoint)
          self.rxContents = msgStr
          print("这是单播数据")
        }
      }
    }
    group.stateUpdateHandler = { (newState) in
      print("Group entered state \(String(describing: newState))")
    }
    group.start(queue: .main)
  }
}

备选方案:开启端口复用同时保留两个实例

如果确实需要分开处理单播和多播逻辑,可以给两个对象都配置端口复用参数,允许同一端口被多个socket绑定:

// 配置UDP参数开启端口复用
let udpParams = NWParameters.udp
udpParams.allowLocalAddressReuse = true
udpParams.allowPortReuse = true

// 初始化NWListener时用自定义参数
guard let listener = try? NWListener(using: udpParams, on: 3610) else { fatalError() }

// 初始化NWMulticastGroup时也用自定义参数
guard let multicast = try? NWMulticastGroup(for: [ .hostPort(host: "224.0.23.0", port: 3610) ], disableUnicast: false, parameters: udpParams) else { fatalError() }

注意事项

  • 需要在项目中添加com.apple.developer.networking.multicast权限声明,否则多播数据会被系统拦截
  • iOS 14及以上版本需要主动申请本地网络权限,用户同意后才能正常收发局域网UDP数据
  • NWMulticastGroup的disableUnicast参数最低支持iOS 14、macOS 11系统

内容的提问来源于stack exchange,提问作者Hiro Fujita

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 07:00:04