【问题标题】:Java Messaging SystemJava消息系统
【发布时间】:2015-12-13 21:40:05
【问题描述】:

我正在创建一个 Java 文件发送程序。现在我正在尝试实现一个聊天消息系统。

这里是调用服务器/客户端代码的代码:

if(host.isSelected()) {
        Server server = new Server();
        ServerChat serverChat = new ServerChat();
        server.Thread();
        serverChat.Thread();
    }
else if(guest.isSelected()) {
        Client client = new Client();
        ClientChat clientChat = new ClientChat();
        client.Thread();
        clientChat.Thread();
}

这会调用以下类中的代码:ServerChat

public class ServerChat extends Main implements Runnable {

public static ServerSocket ss;
public static Socket s;
public static DataInputStream dis;
public static DataOutputStream dos;

public void Thread() {
    (new Thread(new ServerChat())).start();
}

@Override
public void run() {
    String variable = "";

    try {
        ss = new ServerSocket(1234);
        s = ss.accept();

        dis = new DataInputStream(s.getInputStream());
        dos = new DataOutputStream(s.getOutputStream());

        while (!variable.equals("exit")) {
            variable = dis.readUTF();
            chatText.setText(chatText.getText().trim() + "\n Client:\t" + variable);
        }
    } catch (Exception e) {

    }

    if (send.isSelected()) {
        try {
            String messageOut = "";
            messageOut = chatText.getText().trim();
            dos.writeUTF(messageOut);
        } catch (Exception e) {

        }
    }
}
}

客户聊天代码:

public class ClientChat extends Main implements Runnable {

    public void Thread() {
        (new Thread(new ClientChat())).start();
    }

    @Override
    public void run() {
        try {
            socket = new Socket("localhost", 1234);
            dis = new DataInputStream(socket.getInputStream());
            dos = new DataOutputStream(socket.getOutputStream());
            String variable = "";

            while (!variable.equals("exit")) {
                variable = dis.readUTF();
                chatText.setText(chatText.getText().trim() + "\n Server:\t" + variable);
            }
        } catch (Exception e) {

        }

        if (send.isSelected()) {
            try {
                String messageOut = "";
                messageOut = chatText.getText().trim();
                dos.writeUTF(messageOut);
            } catch (Exception e) {

            }
        }
    }
    }

它们能够相互连接,但数据没有发布到我在主类中创建的文本框中。 (主要需要的所有元素都是公共的)。

当我连接(通过 locahost)时,我通过一个新类创建服务器并打开一个新线程

public class Server extends Main implements Runnable {

public ServerSocket welcomeSocket;
public String file;
public DataOutputStream dos;
public DecimalFormat df = new DecimalFormat("##, #00");
public BufferedReader inFromClient;

public void Thread() {
    (new Thread(new Server())).start();
}

@Override
public void run() {

    try {
        InetAddress localaddr = InetAddress.getLocalHost();
        chatText.append("Local IP Address : " + localaddr);
        chatText.append("Local hostname : " + localaddr.getHostName());
        String clientSentence = null;
        String capitalizedSentence;
        welcomeSocket = new ServerSocket(1234);
        String file = "";
        DecimalFormat df = new DecimalFormat("##, #00");

        while (true) {
            Socket connectionSocket = welcomeSocket.accept();
            inFromClient
                    = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
            DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());

            clientSentence = inFromClient.readLine();
            System.out.println("Received: " + clientSentence);
            capitalizedSentence = clientSentence.toUpperCase() + '\n';
            outToClient.writeBytes(capitalizedSentence);
        }
    } catch (Exception e) {
        chatText.append("Unable to create server");
        chatText.append("Can't detect local host : " + e);
    }
}

客户端也是如此:

public class Client implements Runnable {

public DataOutputStream dos;
public DataInputStream dis;
public Socket skt;
public StringTokenizer st;

public void Thread() {
    try {
        dos = new DataOutputStream(skt.getOutputStream());
        dis = new DataInputStream(skt.getInputStream());
    } catch (Exception e) {
        System.out.println(e.getMessage());
    }
    (new Thread(new Client())).start();
}

@Override
public void run() {
    try {
        InetAddress localaddr = InetAddress.getLocalHost();
        skt = new Socket("localhost", 1234);
        BufferedReader in = new BufferedReader(new InputStreamReader(skt.getInputStream()));

        while (!Thread.currentThread().isInterrupted()) {
            String data = dis.readUTF();
            st = new StringTokenizer(data);
            String CMD = st.nextToken();
            JFileChooser open = new JFileChooser();
            open.showOpenDialog(null);
            File f = open.getSelectedFile();
            String fileName = f.getAbsolutePath();
            FileInputStream fs = new FileInputStream(fileName);

            switch (CMD) {
                case "CMD_SENDFILE":
                    try {
                        fileName = st.nextToken();
                        System.out.println("Receiving file...");
                        String path = System.getProperty("user.home");
                        File file = new File(path + "/Downloads" + fileName + ".txt");
                        FileOutputStream fos = new FileOutputStream(path);
                        InputStream input = skt.getInputStream();
                        byte[] buffer = new byte[1024];
                        int count, percent = 1;
                        while ((count = input.read(buffer)) > 0) {
                            percent = percent + 1;
                            fos.write(buffer, 0, count);
                        }

                        fos.close();
                        System.out.println("File was saved: " + path);
                    } catch (Exception e) {
                        DataOutputStream eDos = new DataOutputStream(skt.getOutputStream());
                        System.out.println(e.getMessage());
                        skt.close();
                    }

                    break;
            }
        }

        /*String string = in.readLine();
        System.out.println("Incoming: " + string + "\n");
        System.out.println("Incoming: " + in.readLine() + "\n");
        //in.close();*/
    } catch (Exception e) {
        System.out.println("Error could not connect\n");
    }
}
}

【问题讨论】:

  • 让我猜猜——你的 GUI 是一个 Swing GUI,如果你试图和它聊天,它就会完全冻结,是不是很接近?
  • 如果是这样,您的代码将完全忽略所有线程问题(更不用说忽略所有异常——您应该永远这样做)。
  • 是的,这是一个秋千,但我创建了一个新线程,这样它就不会冻结
  • 您需要改进这个问题,然后包括发布更多代码,尽可能接近minimal reproducible example 的代码。请阅读要求以了解有关此工具的更多信息。我们需要看看你的 GUI 和非 GUI 代码是如何交互的,这是我们看不到的。是的,当您在后台线程中进行 Swing 调用时,您忽略了线程问题,这可能会导致间歇性难以调试异常。但首先,请至少从您的 catch 块中打印您的堆栈跟踪。您可能会抛出异常并且不知道它们。
  • 请注意,minimal reproducible example 不是完整的代码转储,我们不接受链接中发布的代码,仅接受此处发布的代码。我发布此内容是为了让您有最好的机会获得对您的问题的体面答案。

标签: java swing


【解决方案1】:

你的主要问题在这里:

public class ClientChat extends Main implements Runnable {

您误用了继承。不使用继承,以便一个实例可以与另一个实例共享变量,这就是您尝试使用它的目的。相反,它主要用于共享行为。我强烈建议 ClientChat 不要扩展 Main 而是有一个 Main 字段,它可以调用它的公共方法。

您的另外两个问题是较小的问题,但它们仍然会让您头疼:

  • 您通常希望避免在执行操作时忽略异常。至少让 catch 块打印堆栈跟踪:e.printStackTrace();
  • 您需要确保在 Swing 事件线程上进行 Swing 调用,包括对文本组件上的 setText(...) 的调用。如果您使用的是普通的普通线程,则可以通过SwingUtilities.invokeLater(new Runnable() {...}); 完成。否则,请考虑使用 SwingWorker,这将通过其发布/处理方法对帮助您自动执行此操作。

你问过:

关于继承,有没有我可以看的关于调用 ClientChat 的主要字段的帖子?

查找“继承与组合”——您将在此处使用后者,即组合,而不是继承。

您可能希望在 GUI 或代码的“查看”部分与聊天引擎或代码的“模型”部分之间来回传递信息。有几种方法可以做到这一点,但通常它们会通过某种类型的“控制”类或多个类连接,即所谓的“MVC”或“模型-视图-控制器”架构。

【讨论】:

  • 关于继承,有没有我可以看的关于调用 ClientChat 的主要字段的帖子?
猜你喜欢
  • 2012-02-02
  • 1970-01-01
  • 1970-01-01
  • 2011-01-18
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多