如何以编程方式取消从 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中以编程方式取消选中复选框