如何通过编程取消从输入流中读取数据?

3
我在StackOverflow和Google上查找了许多,但未能找到解决我的问题的方法。这里是我正在做的事情。
我有一个控制台应用程序的服务器,用户使用任何Telnet客户端连接到它。我使用三个单独的线程来处理客户机,一个线程(ClientThread)控制对客户机的所有程序访问,ClientThread维护两个线程,一个用于处理输入,一个用于发送输出。ClienThread读取客户端套接字并将输入(如果有的话)发送到ProcessingThread,该线程处理输入并执行用户指定的操作。输出线程管理需要发送的输出队列,并在每次唤醒时发送它。当用户断开连接时,我偶尔会使用位于输出"队列"中的输出,直到连接被终止为止,因此我想设置连接保持活动状态,直到输出队列为空。然而,读取套接字的线程(最终关闭它),现在阻塞在读取时,我无法关闭它。以前当用户断开连接时,我只需关闭套接字,这不是问题。下面是相关代码。
public class ClientThread extends Thread {
   // Initialization and other code not pertaining to the problem 

   public void run() {
      while (connected) {
         try {
            String input = in.readLine();

            if (input != null) {
               processor.queue(TextUtility.processBackspaceChars(input));
               timeoutTimer.interrupt();
            }
         } catch (Exception e) {
            if (e.getMessage() != null && !(e.getMessage().equals("socket closed")))
               server.appendError("Issue reading from client: "
                     + getClientDisplayInfo() + "\n"
                     + "&r-The issue is:&w- " + e.getMessage() + "&r-.");
         }
      }

      while (disconnecting) {
         try {
            if (outputThread.hasOutput()) {
               sleep(10);

            } else {
               disconnecting = false;
               outputThread.disconnect();
               client.close();
            }
         } catch (Exception exc) { 
            server.appendError("Failed to close the Thread for client: " + getClientDisplayInfo());
         }
      }  
   }   

   public void disconnect() {
      try {
         connected = false;
         disconnecting = true;
         processor.disconnect();
         timeoutTimer.disconnect();
         in.close(); // This is the BufferedReader that reads the Socket Input Stream
         this.interrupt(); // This was my attempt to break out of the read, but it failed

      } catch (Exception e) {
         server.appendError("Failed to close the Thread for client: " 
               + getClientDisplayInfo());
      }
   }
}

我只是好奇如何在不关闭Socket的情况下取消读取,因为我需要继续发送输出。


虽然Stacker的回答完美地解决了问题,但是随着多个客户端的出现,它无法扩展。我怀疑这个程序永远不会支持大量的客户端,但我仍在尽可能地提高其效率。最终我采取的解决方案是,当OutputThread收到“断开连接”的通知时,会更改一个标志,并在其输出队列为空时立即通知客户端关闭套接字。这样可以保持一切运行相同的方式,以便在几秒钟内清除输出队列。 - Brandon Buck
2个回答

4

我猜它类似于我昨天遇到的问题yesterday。在进行(阻塞式)读取之前,您可以在输入流上调用is.available()并检查是否有数据可用。


谢谢,这个方法非常有效。在我发布这篇文章之后,我意识到我可以向OutputThread添加一个标志,告诉客户端在Socket为空时关闭它。但是你的方法也完美地解决了问题,感谢你的回答(除了Google/StackOverflow,我想我应该参考一下Sockets的API)。 - Brandon Buck
这将涉及对流进行持续轮询以获取新数据。这仅适用于少量客户端。这根本无法扩展。通常情况下,您永远不会这样做,但对于小型、低负载程序,这将起作用。 - Jay

3

不要调用available()方法:如果你过于频繁地调用它,将浪费CPU资源;如果你不够频繁地调用它,响应时间会受到影响。在Socket上设置读取超时时间,并让读取线程每次触发时检查一个“取消”标志;从任何你想设置的位置设置该标志。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接