我正在使用套接字编写Java客户端/服务器GUI应用程序,这就是问题所在:
我有一个开始侦听指定端口的按钮:
按钮actionPerformed方法
private void listenButtonActionPerformed(java.awt.event.ActionEvent evt) {
int port = Integer.parseInt(portTextfield.getText(), 10);
try {
socket.listen(port);
} catch (IOException ex) {
}
}
这是socket.listen方法
public static void listen() throws IOException {
ServerSocket ss = new ServerSocket(port);
while (true)
new socket(ss.accept());
}
“socket”类扩展“Thread”
因此,在ss.accept()返回一个值后,它会在单独的线程中创建新的套接字实例。
点击按钮后,GUI冻结,因为在socket.listen方法中有一个无限循环。我怎么能避免这种情况?
答案 0 :(得分:5)
你的设计中有两个陷阱:
ss.accept()
是一个阻止调用,因此您的用户界面将冻结,直到有传入连接while(true)
个循环。 而是执行以下操作:
答案 1 :(得分:5)
只要你的
new socket(ss.accept());
立即返回,您只需要更改
while (true)
这会使EDT(事件调度线程)进入无限循环,并且您的GUI变得无法响应。所以,删除这一行。
如果你不能那么使用SwingWorker类(http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html#process(java.util.List) 创建一个扩展SwingWorker的嵌套类。只需在 listenButtonActionPerformed(java.awt.event.ActionEvent evt)方法中调用 swingWoker.execute(); (在创建其对象之后)。
请参阅教程:http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
永远不要创建新线程并从Swing EDT
运行它答案 2 :(得分:3)
您需要使用多线程。如果我在哪里,我会将GUI代码和服务器代码分开,当按下按钮时,我只需将服务器代码作为新线程启动。
您的代码基本上冻结了GUI,因为所有事件都在事件调度程序线程(EDT)上执行,该线程负责处理所有GUI内容和相应事件。如果您阻止它,停止它或抛出循环它将影响它的性能。
答案 3 :(得分:3)
检查出来:http://javarevisited.blogspot.ro/2012/02/what-is-blocking-methods-in-java-and.html
1)如果您正在编写GUI应用程序,可能在Swing中从不调用 Event调度程序线程或事件处理程序中的阻塞方法。 例如,如果您正在读取文件或打开网络连接 单击一个按钮时不要在actionPerformed()方法上执行此操作, 相反,只需创建另一个工作线程来完成该工作并返回 来自actionPerformed()。这将使您的GUI保持响应,但又一次 如果操作是需要的,它取决于设计 用户等待考虑使用invokeAndWait()进行同步 更新
使用多个帖子:http://javarevisited.blogspot.ro/2011/02/how-to-implement-thread-in-java.html
答案 4 :(得分:2)
试试这些......
1. During getting the initial connection delay can occur, so first create and empty
socket,then try to connect to the server.
`Socket s = new Socket();`
`s.connect(new InetSocketAddress("ip_addr",port_nos),1000);`
2. And Secondly always keep the Non-UI work out of Your UI thread..
这是我的服务器示例 - 客户端通信..
客户端代码:
public class ClientWala {
public static void main(String[] args) throws Exception{
Boolean b = true;
Socket s = new Socket();
s.connect(new InetSocketAddress("127.0.0.1", 4444),1000);
System.out.println("connected: "+s.isConnected());
OutputStream output = s.getOutputStream();
PrintWriter pw = new PrintWriter(output,true);
// to write data to server
while(b){
if (!b){
System.exit(0);
}
else {
pw.write(new Scanner(System.in).nextLine());
}
}
// to read data from server
InputStream input = s.getInputStream();
InputStreamReader isr = new InputStreamReader(input);
BufferedReader br = new BufferedReader(isr);
String data = null;
while ((data = br.readLine())!=null){
// Print it using sysout, or do whatever you want with the incoming data from server
}
}
}
服务器端代码:
import java.io.*
import java.net.*;
public class ServerTest {
ServerSocket s;
public void go() {
try {
s = new ServerSocket(44457);
while (true) {
Socket incoming = s.accept();
Thread t = new Thread(new MyCon(incoming));
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
class MyCon implements Runnable {
Socket incoming;
public MyCon(Socket incoming) {
this.incoming = incoming;
}
@Override
public void run() {
try {
PrintWriter pw = new PrintWriter(incoming.getOutputStream(),
true);
InputStreamReader isr = new InputStreamReader(
incoming.getInputStream());
BufferedReader br = new BufferedReader(isr);
String inp = null;
boolean isDone = true;
System.out.println("TYPE : BYE");
System.out.println();
while (isDone && ((inp = br.readLine()) != null)) {
System.out.println(inp);
if (inp.trim().equals("BYE")) {
System.out
.println("THANKS FOR CONNECTING...Bye for now");
isDone = false;
s.close();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
try {
s.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new ServerTest().go();
}
}