试图从输入流检索文本时,应用程序会悬挂



情况

我一直在创建一个程序来在LAN中的两台计算机之间交换消息。一台计算机将自己标识为服务器,而另一台是客户端。启动时,如果他希望以客户端连接到该计算机,则必须输入主机和另一台计算机的端口。它的工作方式的设置非常基本:您输入消息,点击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()方法,但是一旦我注意到它不起作用,就决定尝试使用Compon.io方法(与当前面对的问题相同)。

问题

现在已经很清楚了:为什么我的程序在我单击一个检索新消息的按钮时挂起?

外部

我不确定它是否被皱眉了,但这是GitHub存储库,以防您想要更好的概述,尽管我相信必要的代码狙击手在那里。

我确实查看了您的代码,正如我所怀疑的那样,您的问题与您发布的代码无关。您的GUI完全忽略了挥杆线规则,并在主秋千事件线程中调用长期运行的任务,称为 e vent d ispatch t hread或 EDT 。由于此线程负责所有摇摆图和用户互动,因此您的GUI被阻止了并完全冷冻。

请阅读有关此详细信息的摇摆的并发。

下次,请发布SSCCE,以便我们不必深入了解您的大量源代码!SSCCE的关键是消除所有对于您的问题而不是必需的代码。这并不容易做,需要您的大量工作才能创建,以便它有足够的代码运行,但不要太多以淹没我们的代码,但是您要求志愿者帮助您免费提供他们的免费时间,所以这不是问太多。

好运!

,没有阅读您的所有说明和所有代码附件,我可以假设您正在阅读或写入流到UI线程中(例如,直接从Action或ActionListener调用IO操作读/写。

请检查您的代码。我相信您会发现您致电in.read()out.write()的点。在线路之前和之后添加打印。您会看到您永远不会退出读写。

这是因为另一侧的执行不相反。因此,您必须:

  1. 将UI与IO脱离。io必须在单独的线程中完成。
  2. 检查为什么其他侧阻止您的流动。