Anleitung zum XMPP Smack Client

1. Einleitung

XMPP ist ein umfangreiches und komplexes Instant Messaging-Protokoll.

Anstatt unseren eigenen Client von Grund auf neu zu schreiben , werfen wir in diesem Tutorial einen Blick auf Smack, einen modularen und portablen Open-Source-XMPP-Client, der in Java geschrieben wurde und einen Großteil der Arbeit für uns geleistet hat.

2. Abhängigkeiten

Smack ist in mehrere Module unterteilt, um mehr Flexibilität zu bieten , sodass wir die benötigten Funktionen problemlos einbinden können.

Einige davon sind:

  • XMPP über TCP-Modul
  • Ein Modul zur Unterstützung vieler der von der XMPP Standards Foundation definierten Erweiterungen
  • Unterstützung für ältere Erweiterungen
  • Ein Modul zum Debuggen

Alle unterstützten Module finden Sie in der XMPP-Dokumentation.

In diesem Tutorial verwenden wir jedoch nur die Module tcp , im , extensions und java7 :

 org.igniterealtime.smack smack-tcp   org.igniterealtime.smack smack-im   org.igniterealtime.smack smack-extensions   org.igniterealtime.smack smack-java7 

Die neuesten Versionen finden Sie bei Maven Central.

3. Setup

Zum Testen des Clients benötigen wir einen XMPP-Server. Zu diesem Zweck erstellen wir ein Konto auf jabber.hot-chilli.net, einem kostenlosen Jabber / XMPP-Dienst für alle.

Anschließend können wir Smack mithilfe der XMPPTCPConnectionConfiguration- Klasse konfigurieren , die einen Builder zum Einrichten der Verbindungsparameter bereitstellt:

XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder() .setUsernameAndPassword("baeldung","baeldung") .setXmppDomain("jabb3r.org") .setHost("jabb3r.org") .build();

Mit dem Builder können wir die grundlegenden Informationen festlegen, die zum Herstellen einer Verbindung erforderlich sind . Bei Bedarf können wir auch andere Parameter wie Port, SSL-Protokolle und Zeitüberschreitungen festlegen.

4. Verbindung

Das Herstellen einer Verbindung wird einfach mithilfe der XMPPTCPConnection- Klasse erreicht:

AbstractXMPPConnection connection = new XMPPTCPConnection(config); connection.connect(); //Establishes a connection to the server connection.login(); //Logs in 

Die Klasse enthält einen Konstruktor, der die zuvor erstellte Konfiguration akzeptiert. Es bietet auch Methoden zum Herstellen einer Verbindung zum Server und zum Anmelden.

Sobald eine Verbindung hergestellt wurde, können wir die Funktionen von Smack wie den Chat verwenden , die wir im nächsten Abschnitt beschreiben werden.

Für den Fall, dass die Verbindung plötzlich unterbrochen wurde, versucht Smack standardmäßig, die Verbindung wiederherzustellen.

Der ReconnectionManager versucht, sofort wieder eine Verbindung zum Server herzustellen und die Verzögerung zwischen den Versuchen zu erhöhen, da aufeinanderfolgende Wiederverbindungen weiterhin fehlschlagen.

5. Chat

Eine der Hauptfunktionen der Bibliothek ist die Chat-Unterstützung.

Mit der Chat- Klasse können Sie einen neuen Nachrichten-Thread zwischen zwei Benutzern erstellen:

ChatManager chatManager = ChatManager.getInstanceFor(connection); EntityBareJid jid = JidCreate.entityBareFrom("[email protected]"); Chat chat = chatManager.chatWith(jid);

Beachten Sie, dass wir zum Erstellen eines Chats einen ChatManager verwendet und natürlich angegeben haben, mit wem wir chatten möchten . Letzteres haben wir mit dem EntityBareJid- Objekt erreichtUmschließt eine XMPP-Adresse - eine JID -, die aus einem lokalen Teil ( baeldung2 ) und einem Domain-Teil ( jabb3r.org ) besteht.

Danach können wir eine Nachricht mit der send () -Methode senden :

chat.send("Hello!");

Und empfangen Sie Nachrichten, indem Sie einen Listener einstellen:

chatManager.addIncomingListener(new IncomingChatMessageListener() { @Override public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) { System.out.println("New message from " + from + ": " + message.getBody()); } });

5.1. Räume

Neben dem End-to-End-Benutzer-Chat bietet Smack Unterstützung für Gruppen-Chats durch die Verwendung von Räumen .

Es gibt zwei Arten von Zimmern: Sofortzimmer und reservierte Zimmer.

Sofortige Räume stehen für den sofortigen Zugriff zur Verfügung und werden basierend auf einer Standardkonfiguration automatisch erstellt. Auf der anderen Seite werden reservierte Räume vom Raumbesitzer manuell konfiguriert, bevor jemand eintreten darf.

Lassen Sie uns einen Blick darauf werfen, wie Sie mit MultiUserChatManager einen Sofortraum erstellen :

MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection); MultiUserChat muc = manager.getMultiUserChat(jid); Resourcepart room = Resourcepart.from("baeldung_room"); muc.create(room).makeInstant();

In ähnlicher Weise können wir einen reservierten Raum erstellen:

Set owners = JidUtil.jidSetFrom( new String[] { "[email protected]", "[email protected]" }); muc.create(room) .getConfigFormManger() .setRoomOwners(owners) .submitConfigurationForm();

6. Dienstplan

Eine weitere Funktion von Smack ist die Möglichkeit, die Anwesenheit anderer Benutzer zu verfolgen.

Mit Roster.getInstanceFor () können wir eine Roster- Instanz erhalten:

Roster roster = Roster.getInstanceFor(connection);

Der Dienstplan ist eine Kontaktliste, die die Benutzer als RosterEntry- Objekte darstellt und es uns ermöglicht, Benutzer in Gruppen zu organisieren.

Wir können alle Einträge in dem Druck Roster die Verwendung getEntries () Methode:

Collection entries = roster.getEntries(); for (RosterEntry entry : entries) { System.out.println(entry); }

Darüber hinaus können wir mit einem RosterListener auf Änderungen in den Einträgen und Anwesenheitsdaten achten:

roster.addRosterListener(new RosterListener() { public void entriesAdded(Collection addresses) { // handle new entries } public void entriesDeleted(Collection addresses) { // handle deleted entries } public void entriesUpdated(Collection addresses) { // handle updated entries } public void presenceChanged(Presence presence) { // handle presence change } });

Es bietet auch eine Möglichkeit, die Privatsphäre des Benutzers zu schützen, indem sichergestellt wird, dass nur genehmigte Benutzer einen Dienstplan abonnieren können. Zu diesem Zweck implementiert Smack ein auf Berechtigungen basierendes Modell.

Es gibt drei Möglichkeiten, Anwesenheitsabonnementanforderungen mit der Roster.setSubscriptionMode () -Methode zu verarbeiten:

  • Roster.SubscriptionMode.accept_all - Akzeptiert alle Abonnementanforderungen
  • Roster.SubscriptionMode.reject_all - Alle Abonnementanforderungen ablehnen
  • Roster.SubscriptionMode.manual - Verarbeitet Abonnementanforderungen für Präsenz manuell

Wenn wir Abonnementanforderungen manuell bearbeiten möchten , müssen wir einen StanzaListener (im nächsten Abschnitt beschrieben) registrieren und Pakete mit dem Typ Presence.Type.subscribe verarbeiten .

7. Strophe

Zusätzlich zum Chat bietet Smack ein flexibles Framework, um eine Zeilengruppe zu senden und auf eingehende zu warten.

Zur Verdeutlichung ist eine Zeilengruppe eine diskrete semantische Bedeutungseinheit in XMPP. Es handelt sich um strukturierte Informationen, die über einen XML-Stream von einer Entität an eine andere gesendet werden.

Wir können eine Zeilengruppe über eine Verbindung mit der send () -Methode übertragen:

Stanza presence = new Presence(Presence.Type.subscribe); connection.sendStanza(presence);

In the example above, we sent a Presence stanza to subscribe to a roster.

On the other hand, to process the incoming stanzas, the library provides two constructs:

  • StanzaCollector
  • StanzaListener

In particular, StanzaCollector let us wait synchronously for new stanzas:

StanzaCollector collector = connection.createStanzaCollector(StanzaTypeFilter.MESSAGE); Stanza stanza = collector.nextResult();

While StanzaListener is an interface for asynchronously notifying us of incoming stanzas:

connection.addAsyncStanzaListener(new StanzaListener() { public void processStanza(Stanza stanza) throws SmackException.NotConnectedException,InterruptedException, SmackException.NotLoggedInException { // handle stanza } }, StanzaTypeFilter.MESSAGE);

7.1. Filters

Moreover, the library provides a built-in set of filters to process incoming stanzas.

We can filter stanza by type using StanzaTypeFilter or by ID with StanzaIdFilter:

StanzaFilter messageFilter = StanzaTypeFilter.MESSAGE; StanzaFilter idFilter = new StanzaIdFilter("123456");

Or, discerning by particular address:

StanzaFilter fromFilter = FromMatchesFilter.create(JidCreate.from("[email protected]")); StanzaFilter toFilter = ToMatchesFilter.create(JidCreate.from("[email protected]"));

Und wir können den logischen Filteroperator ( AndFilter , OrFilter , NotFilter ) verwenden, um komplexe Filter zu erstellen:

StanzaFilter filter = new AndFilter(StanzaTypeFilter.Message, FromMatchesFilter.create("[email protected]"));

8. Fazit

In diesem Artikel haben wir die nützlichsten Klassen behandelt, die Smack von der Stange bietet.

Wir haben gelernt, wie Sie die Bibliothek konfigurieren, um XMPP-Zeilengruppen zu senden und zu empfangen.

Anschließend lernten wir den Umgang mit Gruppenchats mithilfe der ChatManager- und Roster- Funktionen.

Wie üblich sind alle in diesem Tutorial gezeigten Codebeispiele auf GitHub verfügbar.