关闭聊天后打印消息

时间:2014-04-23 05:53:39

标签: java ejabberd smack system.out

我正在使用smack api开发一个简单的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);
        }
    }
}

错误

当发送者发送消息时,接收者会收到消息(我已经通过调试检查过)但是没有显示它。当我退出接收方的聊天时,它会立即打印所有消息。这仅发送给发送方发送消息的接收方。我不知道我在哪里阻止输出流。问题应该在于我对interruptswaiting while loop

的理解

1 个答案:

答案 0 :(得分:0)

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

如果查看ChatManager,每次聊天都会得到一个帖子。在接收器代码中,chatCreated回调将在该一个线程上发生。然后你坐在那里从stdin读取锁定那个线程。你所看到的是,当你退出时,processMessage回调终于可以自由发射并收到你的消息。

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

其他一些建议:

  • 请勿致电System.exit(0)退出。这会终止JVM,某些代码可能无法完全关闭。只需从main
  • 返回
  • 你的while(true) { Thread.sleep(200); }循环很难看。一个更好的方法是在Semaphore上设置主线程块,并让读者线程在他们获得“退出”时释放锁定。或者在读者线程上拨打Thread#join()