При попадании JButton для подключения к серверу программа зависает

Я делаю простой 1v1 "частный чат", используя TCP в java. В настоящее время у меня проблема, когда я использую JButtons. Это моя первая попытка использовать JButtons и ActionListeners, поэтому я не уверен на 100%, что происходит здесь.

У меня есть два отдельных проекта для Сервера и Клиента. Чтобы скомпилировать их, это должны были быть два отдельных проекта.

Проблема возникает, когда я пытаюсь нажать кнопку на A: Запустить сервер B: Подключиться к серверу.

Кнопка зависает, как если бы она находилась в нажатом состоянии. Во время запуска сервера и нажатия кнопки, чтобы "убрать" кнопку, клиент должен попытаться подключиться. Сервер отправляет MOTD клиенту, и клиент должен распечатать его в текстовое окно. Он печатает MOTD только после закрытия сервера. Опять же, не уверен, почему

Код сервера:

package net.valid4life.chat;

import java.awt.Component;

public class Chat implements ActionListener {

private static final long serialVersionUID = 1L;

private static JFrame mainFrame;
private static JPanel contentPane;

private static JTextArea chatWindow;
private static JTextArea serverWindow;

private static JTextField chatBox;
private static JTextField portBox;

private static JLabel currentStatusL;
private static JLabel portl;
private static JLabel status;

private static JButton startServerButton;

private static int port = 1234;
public static final int NOT_STARTED = 0;
public static final int WAITING_FOR_CLIENT = 1;
public static final int CONNECTED = 2;
private static int currentStatus = NOT_STARTED;

public static String newLine = "\n";

public static boolean started = false;

static ServerSocket listener = null;

public static void initGUI() {

 mainFrame = new JFrame("Chat Server");

 mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 mainFrame.setBounds(100, 100, 450, 300);
 contentPane = new JPanel();
 contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
 mainFrame.setContentPane(contentPane);
 contentPane.setLayout(null);

 chatWindow = new JTextArea();
 chatWindow.setLineWrap(true);
 chatWindow.setEditable(false);
 chatWindow.setBounds(220, 15, 200, 215);
 chatWindow.setAlignmentY(Component.BOTTOM_ALIGNMENT);
 contentPane.add(chatWindow);

 serverWindow = new JTextArea();
 serverWindow.setLineWrap(true);
 serverWindow.setEditable(false);
 serverWindow.setBounds(10, 150, 201, 80);
 contentPane.add(serverWindow);

 chatBox = new JTextField();
 chatBox.setBounds(221, 236, 199, 20);
 contentPane.add(chatBox);
 chatBox.setColumns(10);

 portBox = new JTextField("1234");
 portBox.setBounds(68, 37, 86, 25);
 portBox.setActionCommand("portEnter");
 portBox.setColumns(10);
 contentPane.add(portBox);

 portl = new JLabel("Port:");
 portl.setFont(new Font("Times New Roman", Font.PLAIN, 16));
 portl.setBounds(95, 20, 64, 14);
 contentPane.add(portl);

 status = new JLabel("Status:");
 status.setFont(new Font("Times New Roman", Font.PLAIN, 16));
 status.setBounds(15, 239, 46, 14);
 contentPane.add(status);

 currentStatusL = new JLabel(changeStatus(NOT_STARTED));
 currentStatusL.setFont(new Font("Times New Roman", Font.PLAIN, 16));
 currentStatusL.setBounds(60, 239, 151, 14);
 contentPane.add(currentStatusL);

 startServerButton = new JButton("Start Server");
 startServerButton.setFont(new Font("Times New Roman", Font.PLAIN, 13));
 startServerButton.setBounds(60, 96, 100, 40);
 startServerButton.setActionCommand("start");
 startServerButton.addActionListener(new Chat());
 contentPane.add(startServerButton);

 mainFrame.setVisible(true);

}

public static void main(String[] args) throws IOException {

 initGUI();

}

public void actionPerformed(ActionEvent e) {

 if ("start".equals(e.getActionCommand())) {

 try {
 port = Integer.parseInt(portBox.getText());

 startServerButton.setEnabled(false);

 listener = new ServerSocket(port);
 changeStatus(WAITING_FOR_CLIENT);
 serverWindow.append("The server has started on "
 + listener.getLocalPort());


 } catch (IOException e1) {
 e1.printStackTrace();
 } finally {
 try {
 startServer();
 } catch (IOException e1) {
 e1.printStackTrace();
 }
 }




 }else
 System.out.println("YOU BROKE IT");

}

public static void startServer() throws IOException {
 try {

 System.out.println("Looking for client");
 new ServerThread(listener.accept()).start();
 System.out.println("Found client");

 } catch (Exception e) {
 e.printStackTrace();
 } finally {
 listener.close();
 }
}

public static String changeStatus(int newStatus) {
 String newStatusText;
 switch (newStatus) {
 case 0:
 newStatusText = "Server not started.";
 break;
 case 1:
 newStatusText = "Waiting for client.";
 break;
 case 2:
 newStatusText = "Connected to client.";
 break;
 default:
 newStatusText = "Broken";
 }

 currentStatus = newStatus;
 return newStatusText;
}

public static class ServerThread extends Thread {
 private Socket socket;

 public ServerThread(Socket socket) {
 this.socket = socket;
 Chat.serverWindow.append("New Connection from:"
 + socket.getInetAddress() + Chat.newLine);
 Chat.changeStatus(CONNECTED);
 }

 public void run() {
 try {

 BufferedReader in = new BufferedReader(new InputStreamReader(
 socket.getInputStream()));
 PrintWriter out = new PrintWriter(socket.getOutputStream(),
 true);

 out.println("MOTD:Welcome to the testing phase of this chat!");
 out.println("To view commands simply type /help");

 while (true) {
 String input = in.readLine();
 if (input == null || input.equals(".")) {
 break;
 }
 out.println(input);
 }
 } catch (IOException e) {
 Chat.serverWindow.append("Error handling client");
 } finally {
 try {
 socket.close();
 } catch (IOException e) {
 Chat.serverWindow
 .append("Couldn't close a socket, what going on?");
 }
 Chat.serverWindow.append("Connection with client closed");
 }
 }

}
}

Код клиента:

package net.valid4life.chat;

import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

public class Chat implements ActionListener {

private static JFrame mainFrame;
private static JPanel contentPane;

private static JTextArea chatWindow;

private static JTextField chatBox;
private static JTextField portBox;

private static JLabel currentStatusL;
private static JLabel portl;
private static JLabel status;

private static JButton connectButton;

private static int port = 1234;
private static String hostIP = "127.0.0.1";

public static final int NOT_STARTED = 0;
public static final int WAITING_FOR_SERVER = 1;
public static final int CONNECTED = 2;
private static int currentStatus = NOT_STARTED;

public static boolean serverStarted = false;
private static JTextField IPField;
private static JLabel IPL;

private static BufferedReader in;
private static PrintWriter out;

public static void initGUI() {

public static void connectToServer() throws Exception {

 port = Integer.parseInt(portBox.getText());
 hostIP = IPField.getText();

 Socket socket = new Socket("127.0.0.1", 1234);

 in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
 out = new PrintWriter(socket.getOutputStream(), true);

 for (int i = 0; i < 3; i++) {
 chatWindow.append(in.readLine() + "\n");
 }
 // connectButton.setEnabled(false);
}


public static void main(String[] args) throws Exception {
 initGUI();
 connectToServer();
}

public void actionPerformed(ActionEvent e) {
 if ("start".equals(e.getActionCommand())) {
 try {
 connectToServer();
 } catch (Exception e1) {
 e1.printStackTrace();
 }
 } else {System.out.println("ASDASD");}

 }


public static String changeStatus(int newStatus) {
 String newStatusText;
 switch (newStatus) {
 case 0:
 newStatusText = "Server not started.";
 break;
 case 1:
 newStatusText = "Waiting for client.";
 break;
 case 2:
 newStatusText = "Connected to client.";
 break;
 default:
 newStatusText = "Broken";
 }

 currentStatus = newStatus;
 return newStatusText;
}

}

Заранее спасибо за помощь!

1 ответ

Код сервера работает хорошо, но ваш клиент блокирует connectToServer Dispatching Event при вызове connectToServer.

Диспетчерский поток событий отвечает за, среди прочего, обработку запросов на перерисовку и новых входных событий. Если вы заблокируете этот поток по каким-либо причинам, то нет никакого способа, чтобы Thread Dispatching Thread мог обрабатывать любые новые события...

Все блокирующие или длительные задачи должны выполняться вне контекста потока Dispatching Event.

Взгляните на параллелизм в Swing для получения более подробной информации

licensed under cc by-sa 3.0 with attribution.