【问题标题】:Accurately detecting socket sending failures in Java在 Java 中准确检测套接字发送失败
【发布时间】:2012-02-16 10:39:35
【问题描述】:

我正在编写一个 Android 应用程序,它初始化 DatagramSocket 以连接到服务器,然后使用无限循环定期(例如每 5 秒)发送数据包。发送代码如下:

DatagramPacket packet = new DatagramPacket(message, message.length);
try {
    socket.send(packet);
}
catch (IOException e) {
    // Log failure and return
}
// Log success

现在,我可以承受每隔一段时间丢失一个数据包。但是我希望能够在我连接时检测服务器是否不可用(例如崩溃),在这种情况下,我想保留我发送的消息(以便在其他时间发送它们)。最初我认为每次尝试通过此套接字发送数据包时都会引发异常,因此能够处理将消息存储在我的 catch 块中。事实上,它部分有效。我通过关闭服务器来模拟服务器崩溃,当我发送数据包时,我开始收到消息sendto failed: ECONNREFUSED (Connection refused) 的异常。问题是,不是每次发送尝试都会抛出异常,而是每次尝试都会抛出异常 - 所以我的日志看起来像

成功,错误,成功,错误,...

我的理解是,在服务器不可用后第一次尝试发送数据包时,数据包被发送,套接字不会等待查看是否有错误消息,并记录成功。然后在下一次尝试时,套接字尝试发送数据包,看到之前的错误消息,并在不发送数据包的情况下抛出异常,从而导致记录错误。但是,由于没有发送数据包,因此在后续尝试发送数据包时不会再次抛出异常。这是我看到日志后得出的假设,所以我的推理可能会出错。

我的问题是,只要服务器不可用,有没有办法确保每次都抛出异常?或者有没有其他方法可以检测到套接字的另一端已经静默断开?我尝试在循环中检查socket.isConnected(),但它总是返回true

【问题讨论】:

  • @MisterSmith 为什么服务器代码相关?我的目的是处理服务器不可用的情况。
  • 因为我猜你的服务器会为每个传入连接生成一个线程。
  • @MisterSmith 我没有在我的服务器代码中创建任何线程。服务器在单个线程中运行,套接字监听一个端口,并尝试在无限循环中从套接字读取数据包。它不会将任何数据发送回客户端。
  • “服务器不可用”到底是什么意思,是您设置的条件吗?
  • @MisterSmith 是的,我需要能够缓冲被拒绝的数据包,以便以后能够重新传输它们。我测试这个的方式是我关掉我的服务器。

标签: java sockets network-programming


【解决方案1】:

DatagramSocket 的定义是无连接的——这里有一个关于differences between UDP and TCP 的好页面供后代使用。您收到任何错误都表明您正在发送到本地网络上的服务器,该服务器没有响应 arps——或者我们的默认网关正在消失,这不太可能。您的任何send 消息返回错误非常依赖于操作系统和网络,不应依赖 IMO。这也意味着如果你在你和服务器之间放置一个路由器,那么我相信send 方法中的 none 会返回错误。

如果您需要查看服务器是否已启动并已收到您的消息,那么我建议您向服务器添加代码以将确认发送回客户端。您不希望客户端发送并等待每个数据包的确认,但可能会发送 X 个数据包,然后等待所有 X 的确认,或者有一个带有重传线程或其他东西的等待表。

当然,一旦您开始走这条路,您可能需要考虑使用Jgroups 或切换到 TCP/IP。 :-)

【讨论】:

  • 是的。我尝试为我的应用程序输入一些随机 IP 地址和端口号,并且预期没有收到错误消息。所以这是预期的行为。事实上,我遇到了我所说的错误,因为我在与应用程序的 Android 模拟器相同的机器上运行服务器!我想在不切换到 TCP(我真的不需要所有开销)的情况下克服这个问题的唯一方法是确保服务器始终处于运行状态。
猜你喜欢
  • 1970-01-01
  • 2012-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-21
  • 2014-04-15
  • 2023-03-27
  • 1970-01-01
相关资源
最近更新 更多