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

Java使用DatagramPacket发送UDP数据报已发送但客户端无法接收问题求助

问题根因及修复方案

核心错误(直接导致收不到数据)

客户端receive方法的DatagramSocket未绑定到2029监听端口:

  • 你当前写的是DatagramSocket s = new DatagramSocket();,这会让操作系统随机分配一个空闲本地端口,而服务端是固定往2029端口发送数据报,客户端自然收不到。
  • 同时接收用的DatagramPacket不需要指定目标地址,该参数仅用于发送场景。

其他潜在错误(会导致后续运行异常)

  • 服务端receive方法反序列化失败:DatagramChannel.receive写完ByteBuffer后,position指向写入的最后一位,直接调用bb.array()会把缓冲区中未填充的空字节也带入反序列化流程,触发序列化格式错误。需要先调用bb.flip()切换到读模式,再读取有效长度的字节。
  • 资源泄漏:每次调用send/receive方法都新建DatagramChannel/DatagramSocket实例,且未正常关闭资源,多次调用后会出现端口占满、IO异常问题。
  • 多余操作:客户端send方法中已经对DatagramChannel执行了connect操作,调用send方法时不需要再重复传入目标地址。

修复后的核心代码片段

客户端receive方法修复

public Command receive() throws IOException, ClassNotFoundException {
    // 绑定到2029端口监听
    DatagramSocket s = new DatagramSocket(2029);
    // 接收用DatagramPacket不需要指定目标地址
    DatagramPacket inputPacket = new DatagramPacket(new byte[1024],1024);
    s.receive(inputPacket);
    ByteArrayInputStream bais = new ByteArrayInputStream(inputPacket.getData(), 0, inputPacket.getLength());
    ObjectInputStream ois = new ObjectInputStream(bais);
    Command res = (Command) ois.readObject();
    // 用完关闭资源
    ois.close();
    bais.close();
    s.close();
    return res;
}

服务端receive方法修复

public Command receive() throws IOException, ClassNotFoundException {
    SocketAddress socketAddressChannel = new InetSocketAddress("localhost", 1);
    DatagramChannel datagramChannel = DatagramChannel.open();
    datagramChannel.bind(socketAddressChannel);
    ByteBuffer bb = ByteBuffer.allocate(1024);
    datagramChannel.receive(bb);
    // 切换到读模式,取有效字节
    bb.flip();
    byte[] validData = new byte[bb.remaining()];
    bb.get(validData);
    ByteArrayInputStream bais = new ByteArrayInputStream(validData);
    ObjectInputStream ois = new ObjectInputStream(bais);
    Command command =(Command) ois.readObject();
    datagramChannel.close();
    ois.close();
    bais.close();
    return command;
}

优化建议

如果是频繁调用收发方法的场景,建议把DatagramChannel、DatagramSocket实例做成类成员变量,初始化一次复用即可,不需要每次调用都新建销毁,性能更高也更稳定。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 00:48:04