当 socket.close() 抛出 Java 时我能做啥?

Posted

技术标签:

【中文标题】当 socket.close() 抛出 Java 时我能做啥?【英文标题】:Anything I can do when socket.close() throws in Java?当 socket.close() 抛出 Java 时我能做什么? 【发布时间】:2011-10-24 02:33:18 【问题描述】:

一周前开始学习 java,并决定学习处理异常的正确方法。 Java 真的让我发疯了,因为指定方法可以抛出异常作为其签名的一部分。

我目前正在尝试为客户端-服务器应用程序实现多线程服务器。我对socket.close() 可以抛出 IOException 的事实感到非常惊讶。问题是,如果发生了我该怎么办?

...
final Socket socket = .... // at this point I know that I have a good socket
try 
  ..... // communicating with someone on that side....
 catch(IOException e) 
  // communication failed
  // this fact is useful, I can log it
  // and will just hang up
 finally 
  try 
    socket.close(); // bye-bye
   catch(IOException e) 
    // anything but logging I can do here?
  

...

这段代码是在一个单独的线程中执行的,所以我只需要必须捕获所有的异常。问题主要是心理上的 - 我知道,我可以将 catch 块留空,但我试图避免这个技巧。

有什么想法吗?

【问题讨论】:

那里没有很多事情可以做。最近的 Java 7 版本有一个 try-with-resources 块,它会自动关闭您在 try 块中指定的任何资源,这有望永远解决这个问题。这个博客上有一个很好的例子:baptiste-wicht.com/2010/08/java-7-try-with-resources-statement 对语义感到好奇。 FileInputStream.close() throws - 在这种情况下会是什么样子? 快讯:Java 7 is no longer upcoming ;-) @Joachim,你是对的。出于某种原因,我以为是八月底而不是七月 Who cares? 【参考方案1】:

关闭资源失败时您不做任何重大的事情是很常见的。记录日志可能是个好主意,这样您就有机会了解它是否更频繁地发生。

如果关闭资源也是“提交”或以其他方式保持更改,则情况不同:那么您需要像对待任何其他部分的异常一样对待它:处理它。

请注意,Java 7 专门引入了automatic resource management 来简化这些类型的结构。如果您现在学习 Java,那么我建议您使用最新最好的。

【讨论】:

【参考方案2】:

我想这取决于您是从套接字读取数据还是向其写入数据。如果您读取数据并检索到您想要的所有信息,那么您可以放心地忽略该异常。但是,如果您编写数据,您可能不得不假设它没有正确传输。

【讨论】:

【参考方案3】:

Apache Commons IO(一个我几乎无法编写 Java 的库)有一个方法 IOUtils.closeQuietly() 用于此目的。

所以你可以这样做:

final Socket socket = .... // at this point I know that I have a good socket
try 
  ..... // communicating with someone on that side....
 catch(IOException e) 
  // communication failed
  // this fact is useful, I can log it
  // and will just hang up
 finally 
  IOUtils.closeQuietly(socket);

并为自己节省 5 行代码。

作为奖励,closeQuietly() 在套接字为空或已关闭时会做正确的事情。还有其他任何东西 Closeable 的重载。

【讨论】:

socket 为 null 或已经关闭,如果你有一个 null 套接字,那么你的代码、逻辑中确实存在错误。 (final socket = 不应导致 null 而是异常) @bestsss:确实,在给定的代码示例中永远不会发生这种情况。我想说的是IOUtils.closeQuietly() 是一个方便的实用函数,也可以在其他情况下使用。【参考方案4】:

正如 cmets 中所说,您无能为力。我建议你无论如何都要记录一个错误,这样如果它确实发生了,你至少有一个地方可以开始寻找。

【讨论】:

【参考方案5】:

这引起了很多人的注意,强制捕获这样的嵌套异常。

您应该记录它,最好使用像 Log4J 这样强大的工具,否则我会说忽略它是安全的,除了“故意忽略”的评论。

【讨论】:

【参考方案6】:

除了捕获并记录它之外,您无法处理 close 引发的异常。重要的是,如果你让它被抛出,并且如果在到达 close 方法之前抛出了另一个异常,那么 close 方法可能会抛出一个异常来掩盖第一个异常,它不会出现任何地方,你都不会知道真正的问题是什么。所以你肯定不想要那个。

【讨论】:

以上是关于当 socket.close() 抛出 Java 时我能做啥?的主要内容,如果未能解决你的问题,请参考以下文章

Java socket中关闭IO流后,发生啥事

Java socket中关闭IO流后,发生啥事

springboot集成RabbitMQ,Eclipse开发集成RabbitMq,IDEA集成RabbitMQ报错 socket close

jmeter压测时出现socket close关闭的问题

socket.shutdown 与 socket.close

RAII