准确地检测Java中的套接字发送失败

时间:2012-02-16 10:39:35

标签: java sockets network-programming

我正在编写一个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

1 个答案:

答案 0 :(得分:3)

根据定义,

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

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

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