我正在做我的家庭作业,这是关于聊天程序。它有两个接口,一个用于服务器,第二个用于客户端。程序流程如下:
此程序源自 Deitel& Deitel 的 Java How To Program 6e 一书。该示例每个接口只有两个元素:用于显示消息的displayArea(JTextArea)和用于输入消息的输入(JTextField)。
按 Enter 会将消息发送给其他人。
下面是Server.java的一段代码。它在无限循环中做了一些重复的动作。
public void runServer() {
// set up server to receive connections; process connections
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
try {
// Step 1: Create a ServerSocket.
String portNum = txtPort.getText();
server = new ServerSocket(Integer.parseInt(portNum), 100);
InetAddress ip = InetAddress.getLocalHost();
txtServerIP.setText(ip.getHostAddress());
while (true) {
try {
waitForConnection(); // Step 2: Wait for a connection.
getStreams(); // Step 3: Get input & output streams.
processConnection(); // Step 4: Process connection.
}
// process EOFException when client closes connection
catch (EOFException eofException) {
System.err.println("Client terminated the connection.");
}
finally {
closeConnection(); // Step 5: Close connection.
++counter;
}
} // end while
} // end try
// process problems with I/O
catch (IOException ioException) {
ioException.printStackTrace();
}
}
});
} // end method runServer
它适用于原始代码。我决定在接口中添加一些GUI元素,并使用Eclipse Luna 4.4.1添加了一个Application窗口。我添加了IP地址和端口号的输入。然后我添加了一个按钮' Open Connection'对于服务器GUI,另一个按钮“连接到服务器”#39;用于客户端GUI。
现在我运行Server.java,直到我点击' Open Connection'按钮。然后按钮保持按下,尽管我发布并且表单没有响应。之后我运行Client.java并连接到服务器并获得连接成功'服务器的消息。我发送一些消息后关闭客户端窗口,然后突然所有消息都出现在服务器窗口上。
现在我明白,服务器窗口的非响应是因为while ( true )
循环。换句话说,该程序运行良好,但无法足够快地更新界面。我想用一个端口监听器来改变它,或者更快或更敏感的其他东西。
如何更改?
我已经改变了
public void runServer() {
// set up server to receive connections; process connections
SwingUtilities.invokeLater(new Runnable() {...
到
public void runServer() {
// set up server to receive connections; process connections
SwingUtilities.invokeLater(new Thread() {...
但情况仍然不变。
您可以访问我的代码
ServerGUI.java @ http://pastebin.com/pVRi6EfC
ClientGUI.java @ http://pastebin.com/HfftM159
原始代码:
Server.java @ http://pastebin.com/6Q5Z00gb
Client.java @ http://pastebin.com/uCGFGknf
答案 0 :(得分:2)
问题是您使用的是SwingUtilities.invokeLater
。正如this answer所述,invokeLater
执行应用程序主run
内的Thread
正文。由于您的用户界面也在此Thread
中运行,因此您需要使用其他方法。
您希望将此无限循环放在Thread中并明确调用start
,以便它不会阻止您的用户界面。
class MyChatServer extends Thread {
public void run() {
// the while loop
}
}
然后,当您按下“打开连接”按钮时,可以启动Thread
:
MyChatServer server = new MyChatServer();
server.start();
如果没有明确创建新的Thread
,您的应用只能使用一个Thread
。此Thread
将在UI和您需要执行的任何其他工作之间共享。因此,当您进行一些工作(例如while(true)
)时,只会占用您的Thread
,您的用户界面将会冻结,直到再次获得控制权为止。
因此,通过创建新的Thread
,您可以让UI保持控制而不是冻结。
答案 1 :(得分:1)
您的无限循环是忙碌的等待,这会阻止您的UI刷新。你有两个问题:
请等待alternatives。
,而不是忙着等待此外,您应该在引擎的不同线程中使用UI。 您可能还想阅读swing concurrency。