【问题标题】:Unable to receive Message using Smack (Java)?无法使用 Smack (Java) 接收消息?
【发布时间】:2017-06-18 07:12:15
【问题描述】:

我正在尝试设置一个简单的示例,用于使用 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,XMPPdomain是ef-app2所以我设置了buddyJID test2@ef-app2/Smack smack 是默认资源。

编辑

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

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

救命!

【问题讨论】:

  • 发送消息时删除资源:发送到“test2@ef-app2”而不是“test2@ef-app2/Smack”。 Packet Timeout 真的很短,默认是3000,测试的时候增加到5000!代码的第一部分是教程?如果是,我建议删除它,这是误导
  • 感谢@MrPk 的回复,我试过删除smack,但没有用。第一个只是显示我在做什么的示例,我用我正在使用的原始代码对其进行了更新,并且它使用了默认的数据包超时。
  • 现在很清楚了。当我可以时,我会更好地看一下并回复答案;)

标签: java xmpp smack


【解决方案1】:

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

在开始之前,您需要 2 个用户:您可以从 test2@ef-app2 向自己发送消息(您只能使用广播,但它太高级了)。只需在您的服务器上注册第二个用户即可。

所以你需要test1@ef-app2(聊天)和test2@ef-app2(登录你的应用程序)。

首先,我建议你在你的机器上安装Spark 客户端。因此,您将能够拥有一个“确实有效”的客户端,并且您将能够在 Spark 和您的 java 应用程序之间实时与自己聊天,当然使用 2 个用户。我喜欢 Spark,因为它有一个很棒的调试器,可以让你检查发送和接收的节,所以基本上当你不知道自己是否正确时,只需检查 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();这是一个get,而不是set(所以你没有启用它,只是检查......)

要登录,我建议设置一个自定义 资源标识符(有些东西在没有或没有默认值的情况下会中断) -> 避免“Smack”和“ Spark”以更好地调试。使用类似“MyApp”的东西。

connection.login(username, password, "MyApp");  

ChatManagerListener - ChatMessageListener

基本思想是:每次你开始在“我”和“另一个人”之间聊天时,客户端应用程序都必须为“另一个人”的传入消息添加一个监听器。因此,您必须向 ChatManager 添加一个侦听器来管理...单个聊天侦听器。我将向您展示“基本全匿名”版本,如果您愿意,您可以拆分为单个定义的类。

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

主要(聊天应用程序)

基本上,在销毁客户端之前,您必须再等一会儿。如果您将用户“test2”连接到服务器“ef-app2”,使用像我之前提到的 Spark 这样的独立客户端,您将轻松检查是否收到任何消息。 主要将如下所示:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-04
    • 2017-07-21
    • 2016-09-30
    • 1970-01-01
    • 2013-08-27
    • 1970-01-01
    • 1970-01-01
    • 2016-10-26
    相关资源
    最近更新 更多