我正在使用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);
}
}
}
错误:
当发送者发送消息时,接收者会收到消息(我已经通过调试检查过)但是没有显示它。当我退出接收方的聊天时,它会立即打印所有消息。这仅发送给发送方发送消息的接收方。我不知道我在哪里阻止输出流。问题应该在于我对interrupts
或waiting while loop
。
答案 0 :(得分:0)
问题在于回调函数中读循环的位置。
如果查看ChatManager
,每次聊天都会得到一个帖子。在接收器代码中,chatCreated
回调将在该一个线程上发生。然后你坐在那里从stdin读取锁定那个线程。你所看到的是,当你退出时,processMessage
回调终于可以自由发射并收到你的消息。
您需要在chatCreated
中分离读取器线程以处理所有输入。然后立即从回调中返回。实际上,您应该始终创建一个单独的线程来阻止输入。这是正确的做法,即使在像这样的玩具问题中,你也会以奇怪的方式绊倒,所以你不妨养成习惯。
其他一些建议:
System.exit(0)
退出。这会终止JVM,某些代码可能无法完全关闭。只需从main
while(true) { Thread.sleep(200); }
循环很难看。一个更好的方法是在Semaphore上设置主线程块,并让读者线程在他们获得“退出”时释放锁定。或者在读者线程上拨打Thread#join()
。