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

Java UDP局域网设备搜索程序抛出socket closed异常问题咨询

异常产生原因
  1. DatagramSocket#receive() 是阻塞方法,在没有收到UDP数据包时会一直挂起等待。
  2. 按下回车键后,主线程的System.in.read()会结束阻塞,立即执行退出逻辑:
    • UdpProvider中调用provider.exit(),先给done赋值为true,随后直接调用close()关闭DatagramSocket
    • UdpSearcher中调用listener.getDevicesAndClose(),同样先给done赋值为true,随后直接关闭DatagramSocket
  3. 此时子线程大概率还阻塞在ds.receive(receivePak)这一行,正在使用的socket被外部主动关闭,JVM就会抛出java.net.SocketException: socket closed异常。
  4. 额外隐藏问题:代码中done变量没有加volatile修饰,存在多线程可见性问题:主线程修改done的值后,子线程可能感知不到变更,会继续循环执行。
解决方案
  • 首先优化异常处理逻辑,将主动关闭触发的SocketException认定为正常退出场景,不需要打印错误栈,修改子线程的catch块逻辑:
    catch (Exception e) {
        // 非主动退出场景才打印异常栈
        if (!done) {
            e.printStackTrace();
        }
    }
    
  • 给done变量增加volatile修饰,保证多线程可见性,比如UdpProvider里的done修改为:
    private volatile boolean done = false;
    
    UdpSearcher的Listener类中的done变量也要做相同修改。
  • 可选优化:UDP场景下receive()方法阻塞在native层,线程中断无法唤醒,主动关闭socket触发异常属于通用的退出实现方式,只要做好异常过滤即可,不需要额外调整逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 07:12:00