2

我在正在执行的服务器中有一个线程(线程 a) object = ois.readObject();。当我从客户端拔出 LAN 线时,该线程没有出现异常并继续从流中读取。

服务器上的另一个线程(线程 b)每隔一秒尝试向客户端写入一个字节,以检查连接是否仍然存在:checkingStream.writeObject(b);

当我拉这根线时,我得到一个IOExceptionfrom checkingStream.writeObject(b);。我希望“线程 b”导致“线程 a”停止从流中读取并继续执行代码/抛出异常。

threadA.interrupt();不工作。我该怎么办?

4

3 回答 3

5

当我从客户端拔出 LAN 线时,该线程没有出现异常并继续从流中读取。

好吧,我会说这是正确的行为。互联网(通常)和基于 IP 的网络协议旨在对本地中断具有弹性……例如与网络断开连接。

在您的情况下,问题是读取线程所做的任何事情都没有告诉网络堆栈它期望每秒传递一次数据。因此,网络堆栈无法判断网络是否存在问题……或远程服务……或 1 秒内没有数据只是正常行为。

解决方案是按照 EJP 的建议设置读取超时,或者删除旨在检测网络始终存在的内容。我推荐后者。除非您有一个压倒一切的特定应用程序需要知道网络始终存在,否则最好忽略任何短期网络中断,和/或将您的应用程序级协议设计为具有弹性。


线程A.中断();不工作。我该怎么办?

读取超时是一种选择。解除阻塞read调用的另一种方法是close()Socket. 这将导致与套接字关联的 Java 流上的任何未决读取或写入以异常终止。


关于读取超时:

但是这个论坛的其他答案说这是不安全的

在收到超时异常后尝试继续使用套接字是不安全的。如果使用超时,则需要在套接字级别超时后丢弃连接并创建一个新连接。

如果您不想这样做,那么您需要以不同的方式实现超时。例如,创建一个新线程来监视读取线程的状态及其读取的数据。如果新线程没有检测到读取线程的活动,它可以发出警报……同时在读取调用中阻止读取线程,以防连接恢复正常。

于 2012-09-23T04:52:43.987 回答
1

使用 Socket.setSoTimeout() 设置读取超时。捕获 SocketTimeoutException。

于 2012-09-23T04:36:19.820 回答
0

我认为扩展 Thread 类和覆盖interrupt()方法将是一个更好的选择。它会像:

@Override
public void interrupt()
{
    socket.close();
    super.interrupt();
}
于 2013-04-30T12:33:16.677 回答