我正在尝试使用Openfire设置一个使用Smack API发送和接收消息的简单示例。我已经按照tutorial
进行了操作有人问过关于情况here的相同问题,但答案提到我已用于接收聊天的代码。许多these examples也使用相同的方法。
public class Receiver {
public static void main(String a[]) throws XMPPException, InterruptedException {
XMPPConnection connection = new XMPPConnection("192.168.1.38");
System.out.println(connection);
connection.connect();
connection.login("test2", "123456");
EFLogger.LogInfo("Receiver", "Connected [ " + connection.isConnected() + " ]");
connection.getChatManager().addChatListener(new ChatManagerListener() {
public void chatCreated(Chat chat, boolean b) {
System.out.println("In Message Listener ! ");
chat.addMessageListener(new MessageListener() {
public void processMessage(Chat chat, Message message) {
System.out.println("Message [ " + message.toXML());
}
});
try {
chat.sendMessage("Hello");
} catch (XMPPException e) {
e.printStackTrace();
}
}
});
while (true) {
}
}
}
发送时,我正在使用
public class Main {
public static void main(String[] args) throws Exception {
String username = "test";
String password = "123456";
XmppManager xmppManager = new XmppManager("192.168.1.38", 5222);
xmppManager.init();
xmppManager.performLogin(username, password);
xmppManager.setStatus(true, "Hello everyone");
//As @MrPk suggested I shouldn't use "/Smack"
//String buddyJID = "test2@ef-app2/Smack";
String buddyJID = "test2@ef-app2";
String buddyName = "test";
xmppManager.createEntry(buddyJID, buddyName);
for (int i = 0; i < 10; i++) {
xmppManager.sendMessage("Hello mate from test " + i, "test2");
}
boolean isRunning = true;
while (isRunning) {
Thread.sleep(50);
}
xmppManager.destroy();
}
}
这个类是XMPPManager
/**
This class is responsible for handling all Actions related to Chat Management. Connection, Login, Status, Create Entry and Message Listener.
*/
public class XmppManager {
private static final int packetReplyTimeout = 500; // millis
private String server;
private int port;
private ConnectionConfiguration config;
private XMPPConnection connection;
private ChatManager chatManager;
private MessageListener messageListener;
public XmppManager(String server, int port) {
this.server = server;
this.port = port;
}
public void init() throws XMPPException {
EFLogger.LogInfo("XmppManager", String.format("Initializing connection to server %1$s port %2$d", server, port));
SmackConfiguration.setPacketReplyTimeout(packetReplyTimeout);
// SmackConfiguration.DEBUG = true;
config = new ConnectionConfiguration(server, port);
config.isDebuggerEnabled();
connection = new XMPPConnection(config);
connection.connect();
EFLogger.LogInfo("XmppManager", "Connected: " + connection.isConnected());
chatManager = connection.getChatManager();
//messageListener = new MyMessageListener();
}
public void performLogin(String username, String password) throws XMPPException {
if (connection != null && connection.isConnected()) {
EFLogger.LogInfo("XmppManager", "Before login userName [ " + username + " ] password [ " + password + " ]");
connection.login(username, password);
System.out.printf("Logged in ");
}
}
public void setStatus(boolean available, String status) {
Presence.Type type = available ? Type.available : Type.unavailable;
Presence presence = new Presence(type);
presence.setStatus(status);
connection.sendPacket(presence);
}
public void destroy() {
if (connection != null && connection.isConnected()) {
connection.disconnect();
}
}
public void sendMessage(String message, String buddyJID) throws XMPPException {
EFLogger.LogInfo("XmppManager", String.format("Sending mesage '%1$s' to user %2$s", message, buddyJID));
Chat chat = chatManager.createChat(buddyJID, messageListener);
chat.sendMessage(message);
}
public void createEntry(String user, String name) throws Exception {
EFLogger.LogInfo("XmppManager", String.format("Creating entry for buddy '%1$s' with name %2$s", user, name));
Roster roster = connection.getRoster();
roster.createEntry(user, name, null);
}
static class MyMessageListener implements MessageListener {
public void processMessage(Chat chat, Message message) {
String from = message.getFrom();
String body = message.getBody();
EFLogger.LogInfo("XmppManager", String.format("Received message '%1$s' from %2$s", message.getError(), from));
}
}
}
首先我认为buddyID必定存在问题,我有这两个用户test
和test2
而XMPP域名是ef-app2
所以我设置了buddyJID
test2@ef-app2/Smack
smack是默认资源。
@MrPk建议不应该使用 / Smack ,但没有运气。
但是,它没有影响我仍然无法收到任何消息。 我不确定我错过了什么。 如果您有兴趣重现同样的问题,可以找到IntelliJ IDEA项目here 您可以获得有关该问题的更多详细信息here
帮助!
答案 0 :(得分:0)
当我开始聊天应用程序时,我使用了相同的教程。它或多或少是一个很好的教程,但却非常简约:让我们逐点检查主要改进和修复错误。
在开始之前,您需要2个用户:您可以将test2@ef-app2
个消息发送给自己(您只能通过广播进行,但它也可以adavanced主题)。只需在服务器上注册第二个用户。
因此,您需要test1@ef-app2
(与之聊天)和test2@ef-app2
(在您的应用中登录)。
首先,我建议您在计算机上安装Spark客户端。因此,您将能够拥有一个能够确保&#34;确实有效的客户。并且您可以在Spark和您的Java应用程序之间实时聊天,当然使用2个用户。我喜欢Spark,因为它有一个很好的调试器,可以让你检查Stanzas发送和接收,所以基本上当你不知道你是否正确时,只需检查Spark的作用。
SmackConfiguration.setPacketReplyTimeout(3000); //default
不要减少默认超时。我从50000开始,现在我有7000(这意味着7秒)。
之前或之后,您需要改进连接配置,或多或少像这样:
protected XMPPTCPConnectionConfiguration config;
protected AbstractXMPPConnection connection;
this.config = XMPPTCPConnectionConfiguration.builder()
.setServiceName(serviceName) //Often is NOT the IP address of Host
.setHost(server)
.setPort(port)
.setSecurityMode(SecurityMode.disabled) //if you don't need
.setDebuggerEnabled(true) //really helpfull
.build();
this.connection = new XMPPTCPConnection(config);
this.connection.connect();
连接到服务器而不提供用户,密码和资源。
注意:config.isDebuggerEnabled();
它是一个获取,而不是一组(所以你没有启用它,只是只是为了...)
要登录,我建议设置一个自定义 资源标识符(有一些东西可以在没有或默认情况下破坏),这样 - &gt;避免&#34; Smack&#34;和#34; Spark&#34;调试更好。使用&#34; MyApp&#34;。
之类的东西connection.login(username, password, "MyApp");
基本理念是:每当你开始聊天时,我就会#34;和另一个人&#34;,客户端应用程序必须为另一个人&#34;的传入消息添加一个监听器。因此,您必须向ChatManager添加一个监听器来管理...单个聊天侦听器。我会告诉你&#34;基本的所有匿名&#34;版本,如果你愿意的话,你可以分成单个定义的类。
//add to ChatManager a listener to manage incoming "person"
ChatManager.getInstanceFor(connection).addChatListener(
new ChatManagerListener() {
@Override
public void chatCreated(Chat chat, boolean createdLocally)
{
//if it's the first message in session between 2 users
if (!createdLocally)
{
//add a listeners for those message just once
chat.addMessageListener(new ChatMessageListener()
{
@Override
public void processMessage( Chat arg0, Message arg1 )
{
//example to read something in standard output
String from = message.getFrom();
String body = message.getBody();
if (body != null)
{
System.out.println(String.format("============ Received message '%1$s' from %2$s\n============", body, from));
}
else
{
System.out.println("SYSTEM: ping (body null)");
}
}
};
}
}
});
基本上你在销毁客户端之前必须再等一会儿。如果您有用户&#34; test2&#34;连接到服务器&#34; ef-app2&#34;对于像我之前的Spark I一样的独立客户端,如果您收到任何消息,您将很容易检查。 主要看起来像:
xmppManager.performLogin("test2@ef-app2", "123456". "MyApp");
xmppManager.createEntry("test1@ef-app2", "My friend"); //test1 ONE!
xmppManager.sendMessage("Hello world", "test1@ef-app2");
boolean isRunning = true;
while (isRunning) {
Thread.sleep(50000);
i++;
if (i > 2)
{
//xmppManager.performLogout();
isRunning = false;
xmppManager.destroy();
}
}
检查调试发生的事情以及发送和接收的最终XML的内容。您可以与Spark进行比较。 如果默认消息不起作用,请尝试以下代码:
Message message = new Message();
message.setBody(body);
message.setType(Message.Type.chat);
message.setTo("test2@ef-app2");
message.setFrom("test1@ef-app2");
try {
connection.sendStanza(message);
} catch (NotConnectedException e) {
System.out.println("Not connected!");
}