无法使用Smack(Java)接收消息?

时间:2017-02-01 13:51:48

标签: java xmpp smack

我正在尝试使用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必定存在问题,我有这两个用户testtest2而XMPP域名是ef-app2所以我设置了buddyJID test2@ef-app2/Smack smack是默认资源。

修改

@MrPk建议不应该使用 / Smack ,但没有运气。

但是,它没有影响我仍然无法收到任何消息。 我不确定我错过了什么。 如果您有兴趣重现同样的问题,可以找到IntelliJ IDEA项目here 您可以获得有关该问题的更多详细信息here

帮助!

1 个答案:

答案 0 :(得分:0)

当我开始聊天应用程序时,我使用了相同的教程。它或多或少是一个很好的教程,但却非常简约:让我们逐点检查主要改进和修复错误。

在开始之前,您需要2个用户:您可以将test2@ef-app2个消息发送给自己(您只能通过广播进行,但它也可以adavanced主题)。只需在服务器上注册第二个用户。

因此,您需要test1@ef-app2(与之聊天)和test2@ef-app2(在您的应用中登录)。

首先,我建议您在计算机上安装Spark客户端。因此,您将能够拥有一个能够确保&#34;确实有效的客户。并且您可以在Spark和您的Java应用程序之间实时聊天,当然使用2个用户。我喜欢Spark,因为它有一个很好的调试器,可以让你检查Stanzas发送和接收,所以基本上当你不知道你是否正确时,只需检查Spark的作用。

XmppManager

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");  

ChatManagerListener - ChatMessageListener

基本理念是:每当你开始聊天时,我就会#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!");
        }