我正在实现一些 Java 代码,这意味着向远程主机发送周期性(1 秒周期)心跳消息。心跳作为 UDP 单播消息发送到远程主机。我使用的是旧版本的 Netty (3.5.0.Final),因为旧代码库升级 Netty 版本会导致依赖冲突。发送的第一个心跳消息是成功的(通过在发送主机上运行tcpdump来验证),但是在第一个之后发送的所有其他心跳消息都没有被发送。
我的调试工作表明,在发送第一条消息后不久,我打开以发送消息的 Channel 对象正在将状态更改为 isOpen()=false 和 isConnected()=false,并且所有进一步尝试调用其write方法的尝试都在一个ClosedChannelException。我不明白为什么频道会自动关闭。需要做什么才能保持打开状态以发送多条消息?
创建和连接发送 Channel 对象的代码如下所示:
private Channel open() throws InterruptedException {
ChannelFactory channelFactory =
new NioDatagramChannelFactory(Executors.newCachedThreadPool(), InternetProtocolFamily.IPv4);
ConnectionlessBootstrap bootstrap = new ConnectionlessBootstrap(channelFactory);
bootstrap.setPipelineFactory(new HeartbeatSenderPipelineFactory());
ChannelFuture channelFuture =
bootstrap.connect(new InetSocketAddress(remoteHost, heartbeatPort)).sync();
return channelFuture.getChannel();
}
我注意到这个问题的另一个特点。用于接收心跳消息的远程主机上有一个软件,运行时会打开一个 UDP 接收器来接收心跳消息。如果我在远程主机上运行该软件,然后在心跳发送器上运行 Java 软件,远程主机将按预期收到周期性的心跳消息。但是,如果我在心跳发送器上运行 Java 软件,而接收器上的软件没有运行(接收器主机仍在运行,只是软件没有运行),那么tcpdump只报告一条发送到远程主机的消息。所以看起来ClosedChannelException如果接收主机运行软件来接收消息,则不会发生,但为什么呢?如果 UDP 是无连接协议,它不应该能够在不需要远程主机接收消息的情况下发送消息吗?