如何以编程方式取消从 InputStream 中读取?

Posted

技术标签:

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

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

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

【讨论】:

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

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

【讨论】:

以上是关于如何以编程方式取消从 InputStream 中读取?的主要内容,如果未能解决你的问题,请参考以下文章

如何在kivymd python的MDDataTable中以编程方式取消选中复选框

Java中读文件操作

使用 Javascript 以编程方式取消标记 FB 照片

如何以编程方式取消选择 ListViewItem?

如何在 android studio 中以编程方式取消订阅 OneSignal

如何以编程方式(VS 6)取消突出显示 MFC CListCtrl 中先前选择的行?