【问题标题】:How can you programatically cancel reading from an InputStream?如何以编程方式取消从 InputStream 中读取?
【发布时间】:2011-11-16 13:10:18
【问题描述】:

我环顾 StackOverflow 和 Google,但无法找到解决问题的方法,所以这就是我正在做的事情。

我有一个控制台应用程序的服务器,用户使用任何 Telnet 客户端连接到它。我正在使用三个单独的线程处理客户端,一个线程 (ClientThread) 控制对客户端的所有程序访问,ClientThread 维护两个线程,一个用于处理输入,一个用于发送输出。 ClienThread 读取客户端套接字并将输入(如果有)发送到处理输入并执行用户指示的操作的处理线程。输出线程管理一个需要发送的输出队列,并在每次唤醒时发送。当用户断开连接时,我偶尔会使用在连接终止之前留在输出“队列”中的输出,所以我想设置它以便连接保持活动状态,直到输出队列为空 - 但是读取套接字的线程(并最终在没有更多输出时关闭它)挂在读取上,我无法关闭它。在用户断开连接之前,这不是问题,我只是关闭了 Socket。我给你相关代码。

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 时,disconnect 通知标志被更改,并且一旦它的输出队列清空,它就会通知客户端关闭套接字。这可以让所有东西在这几秒钟内以相同的方式运行以清除输出队列。

标签: java multithreading sockets inputstream


【解决方案1】:

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

【讨论】:

  • 谢谢,这很有魅力。在我发布这个之后,我意识到我可以在 OutputThread 添加一个标志,告诉客户端在 Socket 为空时关闭它。但是您的方法也很有效,感谢您的回答(除了 Google/StackOverflow,我想我应该参考 Sockets 的 API)。
  • 这将涉及连续轮询流以获取新数据。这仅适用于少数客户。这根本不会扩展。通常你永远不会这样做,但对于小型、低负载的程序,这将起作用。
【解决方案2】:

不要调用 available():要么浪费 CPU 调用它过于频繁,要么浪费时间没有足够频繁地调用它,因此你的响应时间会受到影响。在 Socket 上设置读取超时,并让读取器线程在每次触发时检查“取消”标志;从你想设置的任何地方设置标志。

【讨论】:

    猜你喜欢
    • 2010-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-25
    • 2013-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多