当命中JButton连接到服务器时,程序会冻结 [英] When hitting a JButton to connect to a server , the program freezes

查看:182
本文介绍了当命中JButton连接到服务器时,程序会冻结的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在java中使用TCP进行简单的1v1私聊。目前,每当我使用JButtons时,我都会遇到问题。这是我第一次尝试使用JButtons和ActionListeners,所以我不是100%肯定这里发生了什么。

I am making a simple 1v1 "private chat" using TCP in java. Currently, i have a problem whenever i am using JButtons. This is my first attempt at using JButtons and ActionListeners so i'm not 100% sure whats going on here.

我有两个独立的服务器和客户端项目。
要编译它们,它必须是两个单独的项目。

I have two separate projects for the Server and the Client. To compile these, it would have to be two separate projects.

当我尝试按下按钮到
时出现问题A:启动服务器
B:连接到服务器。

The problem occurs when i try to hit the button to either A: Start the server B: Connect to the server.

该按钮冻结,就好像它处于推动状态一样。在运行服务器并按下按钮时,要取消按钮,客户端必须尝试连接。服务器向客户端发送MOTD,客户端应将其打印到文本窗口。只有在服务器关闭后才打印出MOTD。再次,不知道为什么

The button freezes as if it is in the pushed state. While running the server and hitting the button, to "unpress" the button, a client has to try and connect. The server sends out a MOTD to the client and the client should print that out onto the text window. It prints out the MOTD only once the server is closed. Again, not sure why

服务器代码:

    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's 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;
}

}

预先感谢您的帮助!

推荐答案

您的服务器代码运行良好,但是当您调用 connectToServer时,您的客户端阻止了事件调度线程

Your server code runs well, but your client is blocking the Event Dispatching Thread when you call connectToServer.

事件调度线程负责处理重绘请求和新输入事件等。如果因任何原因阻止此线程,则事件调度线程无法处理任何新事件...

The Event Dispatching Thread is responsible for, amongst other things, processing repaint requests and new input events. If you block this thread for any reasons, then there is no way that the Event Dispatching Thread can process any new events...

所有阻塞或长时间运行的任务应该是在事件调度线程的上下文中执行。

All blocking or long running tasks should be executed out side of the context of the Event Dispatching Thread.

看看 Swing中的并发更多细节

这篇关于当命中JButton连接到服务器时,程序会冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆