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

Flutter中UDP Socket无法接收数据问题求助

Flutter UDP Server 无法接收客户端数据的解决方案

看起来你的Flutter UDP服务器没收到客户端数据的问题,我帮你梳理几个可能的原因和修复方案:

1. 最容易忽略的:缺少网络权限

不管是Android还是iOS,网络相关操作都需要对应的权限配置,这是很多开发者会漏掉的点:

  • Android:打开android/app/src/main/AndroidManifest.xml,在<manifest>标签内添加:
    <uses-permission android:name="android.permission.INTERNET" />
    
  • iOS:打开ios/Runner/Info.plist,添加网络访问权限配置(测试阶段可以用这个绕过ATS限制):
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
    
    如果你的应用需要严格遵循ATS规则,可以针对特定IP添加例外,不过测试阶段用上面的配置更方便。

2. 未正确处理UDP数据包接收

原代码里在RawSocketEvent.read事件中只调用了一次udpSocket.receive(),但单次read事件可能对应多个待接收的数据包,而且如果receive()返回null(没有更多数据),直接访问data会抛出异常。修改成循环接收所有可用数据包:

static Future openPortUdp(Share share) async {
  await RawDatagramSocket.bind(InternetAddress.anyIPv4, 6868)
      .then((RawDatagramSocket udpSocket) {
    print("UDP server bound to port 6868 successfully"); // 新增日志,确认绑定成功
    udpSocket.listen((RawSocketEvent e) {
      switch (e) {
        case RawSocketEvent.read:
          Datagram? datagram;
          // 循环接收所有待处理的数据包
          while ((datagram = udpSocket.receive()) != null) {
            print("RECEIVED");
            print(String.fromCharCodes(datagram!.data));
            // 如果需要给客户端回复,取消下面的注释即可
            // udpSocket.send(utf8.encode("Got it!"), datagram.address, datagram.port);
          }
          break;
        case RawSocketEvent.readClosed:
          print("READCLOSED");
          break;
        case RawSocketEvent.closed:
          print("CLOSED");
          break;
        default:
          print("Unhandled socket event: $e");
          break;
      }
    });
  });
}

新增的绑定成功日志可以帮你确认服务器是否真的启动并监听了端口。

3. 客户端Lua代码的潜在问题(虽然你说客户端在其他服务器正常,但还是检查下)

原客户端代码有两个小问题,可能导致测试时出现异常:

  • 每次循环都关闭socket,下一次循环再操作已经关闭的socket会报错
  • if (not data1 == nil)的判断逻辑错误,应该是if data1 ~= nil

修正后的客户端代码:

local socket = require("socket")
local udp1 = socket.udp()
udp1:setpeername("192.168.1.24", 6868) -- 远程地址只需要设置一次

while true do
  -- 发送数据时增加错误判断
  local sendSuccess, sendErr = udp1:send("HI")
  if not sendSuccess then
    print("Send failed: " .. sendErr)
    break
  end
  print("Sent 'HI' to server")
  
  -- 设置超时,避免一直阻塞等待响应
  udp1:settimeout(1)
  local data1, recvErr = udp1:receive()
  if data1 then
    print("Received from server: " .. data1)
    break
  elseif recvErr ~= "timeout" then
    print("Receive error: " .. recvErr)
    break
  end
end
udp1:close()

4. 网络环境与防火墙检查

  • 确保Flutter设备(真机/模拟器)和客户端在同一局域网内
  • 如果用的是Android模拟器,访问电脑的UDP服务需要用10.0.2.2作为IP,而不是局域网IP(因为模拟器默认的网关是这个)
  • 检查电脑/设备的防火墙是否拦截了6868端口

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 11:32:55