Java 关闭聊天室后将打印消息

Java 关闭聊天室后将打印消息,java,ejabberd,smack,system.out,Java,Ejabberd,Smack,System.out,我正在开发一个简单的ejabberd聊天工具。 我想为发送方和接收方制作一个程序。这个想法是这样的: 运行该程序时,会询问用户您是想与某人聊天(即想成为发送者)还是等待某人发起聊天(即想成为接收者) 如果您选择发件人,它将询问收件人地址 然后,它将启动与接收器的聊天 相同的代码为: import java.util.*; import java.io.*; import java.lang.*; import org.jivesoftware.smack.Chat; import org.

我正在开发一个简单的
ejabberd
聊天工具。
我想为发送方和接收方制作一个程序。这个想法是这样的:

  • 运行该程序时,会询问用户您是想与某人聊天(即想成为发送者)还是等待某人发起聊天(即想成为接收者)
  • 如果您选择发件人,它将询问收件人地址
  • 然后,它将启动与接收器的聊天
相同的代码为:

import java.util.*;
import java.io.*;
import java.lang.*;

import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.ChatManagerListener;


public class Client implements MessageListener{
    static XMPPConnection connection;

    public void login(String userName, String password) throws XMPPException {
        ConnectionConfiguration config = new ConnectionConfiguration("10.100.99.107",5222,"localhost");
        connection = new XMPPConnection(config);

        connection.connect();
        connection.login(userName, password);
    }

    public Chat createChat(String to) throws XMPPException{
        return connection.getChatManager().createChat(to, this);    
    }  

    public void sendMessage(Chat chat, String message) throws XMPPException {
        chat.sendMessage(message);
    }

    public void disconnect() {
            connection.disconnect();
    }

    public void processMessage(Chat chat, Message message) {
        System.out.println("Here");
        if(message.getType() == Message.Type.chat)
            System.out.println(chat.getParticipant() + " says: " + message.getBody());
    }

    public static void main(String args[]) throws XMPPException, IOException, InterruptedException {
        // declare variables
        final Client client = new Client();
        final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        // turn on the enhanced debugger
        // XMPPConnection.DEBUG_ENABLED = true;

        // Enter your login information here
        System.out.println("Login information:\nusername: ");
        String login_username = br.readLine();
        System.out.print("password: ");
        String login_pass = br.readLine();

        client.login(login_username, login_pass);

        if(connection.isAuthenticated()==true){
            System.out.println("\n"+login_username+" :Successfully logged in");

            final Chat chat;
            System.out.println("Do you want to talk? (y/n)");
            String choice = br.readLine();
            if( choice.equals("y")){
                //Sender's code
                System.out.println("Whom do you want to talk to? - Type contacts full email address:");
                chat = client.createChat(br.readLine());
                chat.addMessageListener(client);

                System.out.println("Enter your message in the console (Type 'quit' to exit.):\n");

                String msg;
                while( !(msg=br.readLine()).equals("quit")) {
                    client.sendMessage(chat, msg);
                }
            }else if(choice.equals("n")){
                //Reciever's code
                ChatManager chatmanager = connection.getChatManager();
                chatmanager.addChatListener( new ChatManagerListener() {
                    @Override
                    public void chatCreated(Chat chatReceived, boolean createdLocally)
                    {
                        System.out.println("Chat Created");

                        chatReceived.addMessageListener(client);

                        System.out.println("Enter your message in the console (Type 'quit' to exit.):\n");
                        String msg;
                        try {
                            while( !(msg=br.readLine()).equals("quit")) {
                                client.sendMessage(chatReceived, msg);
                            }
                        }
                        catch(Exception e){
                            System.out.println(e.getMessage());
                        }
                    }
                });

                //put receiver on waiting
                while (true) {
                    Thread.sleep(200);
                }
            }else{
                System.out.println("Wrong Input");                
            }
            client.disconnect();
            System.exit(0);
        }
    }
}
错误


当发送方发送消息时,接收方接收消息(我通过调试进行了检查),但不显示消息。当我退出接收端的聊天时,它会立即打印所有消息。只有当发送方发送消息时,接收方才会发生这种情况。我不确定我在哪里阻塞了输出流。问题应该出在我对
中断
等待while循环的理解上

问题在于您的读取循环在回调函数中的位置

如果你看一下,你会发现每次聊天都有一个线程。在接收方代码中,
chatCreated
回调将在该线程上发生。然后你坐在那里读stdin的文章来锁定线程。您看到的是,当您退出时,
processMessage
回调终于可以自由启动,您可以收到您的消息

您需要在
chatCreated
中派生一个读卡器线程来处理所有输入。然后您立即从回调返回。事实上,您应该始终创建一个单独的线程来阻止输入。这是正确的方法,即使在像这样的玩具问题上,你也会以奇怪的方式被绊倒,所以你最好养成一个习惯

其他几点建议:

  • 不要调用
    系统。退出(0)
    退出。这会终止JVM,并且某些代码可能不会完全关闭。只需从
    main
  • 你的
    while(true){Thread.sleep(200);}
    循环很难看。一个更好的方法是将主线程块放在一个线程上,并让读线程在获得“退出”时释放锁。或者在读卡器线程上调用
    Thread#join()