gpt4 book ai didi

Java Socket 卡住问题

转载 作者:行者123 更新时间:2023-12-01 14:04:20 24 4
gpt4 key购买 nike

我举了一个我想要的程序的例子。问题是我无法使我的套接字连接正常工作(按照我希望的方式工作)。而且我不知道问题出在哪里。

public class TestChat extends Frame {

public static Panel1 p1;
public static Panel2 p2;
public static TestChat tc;

public TestChat() {
super();
setPreferredSize(new Dimension(800, 600));
setLayout(new BorderLayout());
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});

p1 = new Panel1();
p2 = new Panel2();
add(p1);
}

public static void main(String[] args) {
// TODO code application logic here
tc = new TestChat();
tc.pack();
tc.setVisible(true);
///*
try {
TestChat.p2.run();
} catch (IOException ioe) {
System.out.println("IO here");
}
//*/
}

public void change(int to) {
if (to == 1) {
tc.remove(p2);
tc.add(p1);
}
if (to == 2) {
tc.remove(p1);
tc.add(p2);
}
tc.pack();
}
}

public class Panel1 extends Panel implements ActionListener{

public Button button = new Button("Launch chat");

public Panel1() {
super();
setLayout(new BorderLayout());
Label label = new Label("Launcher panel here");
add(label);
add(button, BorderLayout.SOUTH);
button.addActionListener(this);
}

@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button) {
TestChat.tc.change(2);
/*
try {
TestChat.p2.run();
} catch (IOException ioe) {
System.out.println("IO here");
}
//*/
}
}

}

public class Panel2 extends Panel implements ActionListener {

private static final int LOGIN_MAX = 300;
public static TextArea ta = new TextArea();
public static TextField tf = new TextField();
public static TextArea logins = new TextArea();
public static PrintWriter out = null;
public static String[] loginList = new String[LOGIN_MAX];
public static int loginCount = 0;
public Panel temp = new Panel();
public Button startButton = new Button("Start!");
///*
public String fromServer;
public BufferedReader in = null;
public BufferedReader stdIn;
public Socket kkSocket = null;
//*/

public Panel2() {
setLayout(new BorderLayout());
temp.setLayout(new BorderLayout());
ta.setEditable(false);
tf.addActionListener(this);
startButton.addActionListener(this);
logins.setEditable(false);
temp.add(ta, BorderLayout.CENTER);
temp.add(tf, BorderLayout.SOUTH);
add(temp);
add(logins, BorderLayout.EAST);
add(startButton, BorderLayout.SOUTH);
}

//private static void makeLogins() {
public static void makeLogins() {
String userArea = loginList[0] + "\n";
for (int i = 1; i < loginCount; i++) {
userArea = userArea + loginList[i] + "\n";
}
logins.setText(userArea);
}

public void run() throws IOException {

kkSocket = null;

BufferedReader in = null;

try {
kkSocket = new Socket("localhost", 4444);
out = new PrintWriter(kkSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(kkSocket.getInputStream()));
} catch (UnknownHostException e) {
//System.err.println("Can't host to server.");
System.out.println("Can't host to server.");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to server.");
System.exit(1);
}

BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String fromServer;

while ((fromServer = in.readLine()) != null) {
validate();
if (fromServer.startsWith("cmd_newUser_")) {
loginList[loginCount++] = fromServer.substring(12);
if (loginCount > 1) {
Arrays.sort(loginList, 1, loginCount - 1);
}
makeLogins();
} else if (fromServer.startsWith("cmd_deleteUser_")) {
String tmp = fromServer.substring(15);
for (int i = 0; i < loginCount; i++) {
if (loginList[i].equals(tmp)) {
loginList[i] = "" + ((char) 255);
break;
}
}
Arrays.sort(loginList, 1, loginCount);
loginCount--;
makeLogins();
} else {
ta.append(fromServer + "\n");
}
if (fromServer.equals("Bye.")) {
break;
}
}

out.close();
in.close();
stdIn.close();
}

private void sendStr(PrintWriter out) {
if (tf.getText() != "") {
out.println(tf.getText());
tf.setText("");
}
}

@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == tf) {
sendStr(out);
} else if (e.getSource() == startButton) {
System.out.println("I make some actions in the original proj");
}
}
}

当我以这种方式使用它时,我的程序将连接并且一切正常。但我想在按下按钮时从 Panel1 类开始连接(注释调用)。当我尝试从 Panel1 调用它时,我的整个程序卡住了。问题出在哪里以及如何解决?

附注这是我的服务器代码(以防万一)

public class KKMultiServer extends Frame {

public static int userCount = 0;
public static Label users;
public static KKMultiServerThread[] userList=new KKMultiServerThread[100];
public static int writer=0;
public static int curNum=1;

public KKMultiServer() {
super("Server");
setLayout(new GridLayout(2, 1));
users = new Label("Users online: " + userCount);
add(users);
setLocation(200, 200);
setResizable(false);
setMinimumSize(new Dimension(300, 200));
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
}

public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
boolean listening = true;
KKMultiServer server = new KKMultiServer();
server.pack();
server.setVisible(true);

try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(-1);
}

while (listening) {
userList[writer]=new KKMultiServerThread(serverSocket.accept());
System.out.println("Client added!");
userCount++;
users.setText("Users online: " + userCount);
userList[writer++].start();


}

serverSocket.close();
}
}

最佳答案

  1. 以这种方式使用静态引用是一个非常糟糕的设计。您面临着不确切知道您引用的内容的风险。
  2. Swing 是单线程环境,也就是说,对 UI 的所有交互和修改都应该在事件调度线程的上下文中执行。任何阻塞该线程的操作(例如阻塞 I/O 或长时间运行的循环)都将阻止 UI 处理新事件和绘制请求。

到目前为止,你基本上已经侥幸成功了。当 main 由它所在的 JVM 运行时,通常称为“主”线程。当您开始使用任何 Swing 组件时,Swing API 将启动“事件调度线程”...

所以发生了什么,您正在启动应用程序的 UI 部分,它的上下文正在移至 EDT,而 run 方法 p2 正在继续运行在线程中。

现在您想要从按钮启动通信,您已将执行上下文移至 EDT,这使得您的应用程序看起来像是已挂起......

现在,你有两个问题。第一个是,您需要从 EDT 中获取通信,第二个是,您永远不应该从 EDT 之外的任何线程修改或更新 UI...

有许多解决方案可供您使用,SwingWorker 可能是解决您问题的最简单的解决方案。

看看Concurrency in Swing了解更多详情

关于Java Socket 卡住问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19043931/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com