尝试从输入流中检索文本时,应用程序挂起

情况

我一直在创建一个程序来在局域网中的两台计算机之间交换消息。 一台计算机将自己标识为服务器而另一台计算机标识为客户端。 启动时,如果用户希望作为客户端连接到该计算机,则必须输入另一台计算机的主机和端口。 它的工作原理设置非常基础:您键入消息,按Enter键,它会显示在您自己的屏幕上。 之后,您的对话伙伴必须单击按钮才能检索最新消息,并且它应显示在他的屏幕上。 这种情况一直持续到有人离开。

问题

程序正确启动并询问连接设置。 之后,我在两台计算机上启动连接,事情似乎很顺利(建立连接后,标签会显示您的状态,例如客户端或服务器,是(1))。 当我输入消息并发送消息时,事情继续正常,输出将被写入发送者的屏幕,并且不会发生意外行为。

当我想在另一台计算机上检索消息时,该程序完全冻结。 GUI中没有对象可单击,也不显示输出。

假设连接已正确建立(参见(1)),我将概述下面发送消息的过程,同时省略非必要部分。

GuiApplication.java private void sendMessage() { connection.sendMessage(message); showMessage(message); } Connection.java public void sendMessage(String message) { if (isClient()) { client.sendMessage(message); } else if (isServer()) { server.sendMessage(message); } } Client.java public void sendMessage(String message) { outbound = new PrintWriter(socket.getOutputStream(), true); // Defined outside this method outbound.println(message); } 

发送消息的过程非常简单,但我想包括它以防万一我忽略了一些东西。

以下是我为检索新消息而创建的代码。 这个概念很简单:我检查是否有新消息,如果有,我会检索它们。

 GuiApplication.java if (connection.hasNewMessage()) { message = connection.retrieveMessage(); } showMessage(message); 

第一部分( connection.hasNewMessage() )将检查程序是运行客户端还是服务器并调用相应的retrieveMessage()

 Client.java public String retrieveMessage() throws IOException { inbound = socket.getInputStream(); // Defined outside this method return IOUtils.toString(inbound, "UTF-8"); } 

起初我尝试使用一个BufferedReader使用一个InputStreamReader并调用readLine()方法,但是一旦我注意到它不起作用(与我目前面临的问题相同),我决定尝试使用commons.io方法。

现在已经非常清楚了:为什么我的程序在我点击一个检索新邮件的按钮时挂起?

外部

我不确定它是否令人不满,但这里是 github存储库,以防你需要更好的概述,尽管我相信必要的代码片段就在那里。

我确实查看了你的代码,而且我怀疑你的问题与你发布的代码完全无关。 您的GUI完全忽略Swing线程规则,并在主Swing事件线程上调用长时间运行的任务,称为E vent D ispatch T hread或EDT 。 由于此线程负责所有Swing绘图和用户交互,因此您的GUI无法执行此操作并完全冻结。

有关详细信息,请阅读Swing中的Concurrency 。

下次,请发布一个sscce,这样我们就不必深入了解你的大量源代码! SSCCE的关键是消除对您手头的问题不重要的所有代码。 这不容易做,并且需要你做很多工作才能创建,所以它有足够的代码来运行,但不能太淹没我们的代码,但是你要求志愿者帮助你免费时间,所以不要求太多。

祝你好运!

在没有阅读所有解释和所有代码附件的情况下,我可以假设您正在读取或写入流到UI线程(例如直接从Action或ActionListener调用IO操作,并且在读/写时被阻止。

请检查您的代码。 我相信你会找到你调用in.read()out.write() 。 在行之前和之后添加打印。 您将看到您永远不会退出读取或写入。

这是因为另一方没有执行相反的操作。 所以,你必须:

  1. 从IO中分离UI。 IO必须在单独的线程中完成。
  2. 检查为什么另一边阻挡你的流量。