情况
我一直在创建一个程序来在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()
的点。在线路之前和之后添加打印。您会看到您永远不会退出读写。
这是因为另一侧的执行不相反。因此,您必须:
- 将UI与IO脱离。io必须在单独的线程中完成。
- 检查为什么其他侧阻止您的流动。