Click here to Skip to main content
Click here to Skip to main content

Creating a Jabber Client using the agsXMPP Library

By , 11 Nov 2007
Rate this:
Please Sign up or sign in to vote.

Introduction

I wanted to step a little bit deeper into instant messaging development by using the Jabber protocol. The first place where I looked for an introduction was The Code Project, but I couldn't find any article dealing with Jabber client development. So I thought it's my part to write an article on how to create a small Jabber client, after I got familiar with this stuff.

In this article, I want to introduce Jabber development by a small example application that allows you to chat with one of your Roster contacts. The example is written as a Console Application, but it should be no problem to transfer the code into a small Windows Application.

Jabber/XMPP

Jabber is an open protocol for instant messaging (like Skype). The advantage of Jabber is that as an XML based protocol, it is platform independent and clients can be developed under several operating systems. It also provides the possibility to connect to other instant messaging services like ICQ. Jabber is based on the protocol XMPP (a Jabber derivative) which was standardized in 2004.

A simplified Jabber network looks like this:

Screenshot - JabberClient_Network.jpg

The most important Jabber terms used in this article are:

JID: Jabber ID, looks like an Email address (e.g. Test@TestServer.com) where TestServer.com is the Jabber server (you can find a list of public Jabber servers here).

In the network above, we would have the following JID's:

  • Client1@Server1
  • Client2@Server1
  • Client3@Server2

Roster: List of contacts (friends, family). The Roster can be organized like a tree (as the Jabber protocol is XML based) with folders and the JIDs.

A basic example for a TCP based XMPP stream can look like this:

C: <?xml version='1.0'?>
   <stream:stream
       to='example.com'
       xmlns='jabber:client'
       xmlns:stream='http://etherx.jabber.org/streams'
       version='1.0'>
S: <?xml version='1.0'?>
   <stream:stream
       from='example.com'
       id='someid'
       xmlns='jabber:client'
       xmlns:stream='http://etherx.jabber.org/streams'
       version='1.0'>
...  encryption, authentication, and resource binding ...
C:   <message from='juliet@example.com'
              to='romeo@example.net'
              xml:lang='en'>
C:     <body>Art thou not Romeo, and a Montague?</body>
C:   </message>
S:   <message from='romeo@example.net'
              to='juliet@example.com'
              xml:lang='en'>
S:     <body>Neither, fair saint, if either thee dislike.</body>
S:   </message>
C: </stream:stream>
S: </stream:stream>

Where C is the Client and S is the Server. This example is taken from here.

As an open and standardized protocol, there are plenty of libraries for different programming languages and operating systems available. As I was looking for a C# library, I found the agsXMPP library dealing with the most important tasks like Jabber Client or even Jabber Server development. The agsXMPP is provided under two licenses, the GPL for open source project, and a commercial license for closed source projects.

To get started with the agsXMPP library, you can download the SDK here.

For more detailed information about Jabber/XMPP, you should have a look here and here and here.

Jabber Client

This example application is just a demonstration of how to create a Jabber Client; it does not store any connection data or provide creation of a new account. So if you would like to use the code to develop a real world client, you will have to add some more functionality to the code.

So now we are prepared to develop our own Jabber Client. For this example, I have chosen a Console Application, because it makes the code more readable. As the agsXMPP library provides a lot of events to handle several functionalities that do not make a Console Application the first choice, I think a Windows Forms Application would make it all a little bit confusing on the first view.

So what are the goals of this example application?

  • Create a connection to a Jabber server and authenticate the Jabber user
  • Send the users presence over to the server
  • Handle the presence of the contacts in our Roster (receive all available contacts)
  • Last but not least, the chatting functionality (sending and receiving chat messages)

So let's start.

References

To use the agsXMPP in your own project, you have to add a reference to agsXMPP.dll in your project. For this example, you should also add the following using directives to the header:

using agsXMPP;
using agsXMPP.protocol.client;
using agsXMPP.Collections;
using agsXMPP.protocol.iq.roster;
using System.Threading;

Connection and Authentication

To connect to a Jabber server, we need a JID (Jabber ID) and the corresponding password. At first, we have to create a new JID object with the user's JID as a string parameter. After that, we can create a new XmppClientConnection object with the JID server property of the JID object as a constructor parameter. The code looks like this:

Console.WriteLine("Login");
Console.WriteLine();
Console.WriteLine("JID: ");
string JID_Sender = Console.ReadLine();
Console.WriteLine("Password: ");
string Password = Console.ReadLine();
 
Jid jidSender = new Jid(JID_Sender); 
XmppClientConnection xmpp = new XmppClientConnection(jidSender.Server);

Now we have to open the connection and wait until we are connected and authenticated. In the agsXMPP library, the XmppClientConnection.Open() method is executed asynchronously, so we have to register the OnLogin Eventhandler and wait until the OnLogin event is raised. This is a beautiful solution for a Win App, but it makes a Console App not so beautiful. The code should look like this:

xmpp.Open(jidSender.User, Password);
xmpp.OnLogin += new ObjectHandler(xmpp_OnLogin);

I solved the wait for OnLogin to be raised by a simple do loop, I know there are more pretty solutions, but it just does what it should do:

Console.Write("Wait for Login ");            
_wait = true;
do
{                
    Console.Write(".");
    i++;
    if (i == 10)
         _wait = false;
    Thread.Sleep(500);
} while (_wait); 

So now we have to take a look at the xmpp_OnLogin method:

static void xmpp_OnLogin(object sender)
{
    _wait = false;
    Console.WriteLine("Logged In");            
}

We are just waiting until the OnLogin event is raised (which means we are logged in and authenticated) and then exit the loop to continue our program. Now we can get some information about the Connection and Authentication state of our XmppClientConnection object:

Console.WriteLine("xmpp Connection State {0}", xmpp.XmppConnectionState);
Console.WriteLine("xmpp Authenticated? {0}", xmpp.Authenticated);

Sending the Presence

To show our Roster members we are online, we have to send our presence to the server. This little task works like this:

Presence p = new Presence(ShowType.chat, "Online");
p.Type = PresenceType.available;
xmpp.Send(p);

Now they can see in their Roster that we are online and available for chat (this task is necessary to receive the presence of our Roster members).

Receiving the Presence of our Roster Members

To receive the presence of our Roster members we have to register the OnPresence Eventhandler:

xmpp.OnPresence += new PresenceHandler(xmpp_OnPresence);

Now we have to wait until the event is raised (it is raised now, and if the presence of a Roster member is changed). Attention: we can only see the Roster members where presence type is available.

static void xmpp_OnPresence(object sender, Presence pres)
{
    Console.WriteLine("Available Contacts: ");
    Console.WriteLine(<a href="mailto:%7B0%7D@%7B1%7D%20%20%7B2%7D">{0}@{1}  {2}</a>,
        pres.From.User,pres.From.Server,pres.Type);
    Console.WriteLine();            
}

Sending and Receiving Messages

Now we can start with the most interesting part: Chatting! How does chatting work basically? We send messages to an available chat partner (we need his JID), and we handle received messages in a MessageCallBack method. To prepare for incoming messages, we have to execute the following statement:

xmpp.MesagageGrabber.Add(new Jid(JID_Receiver), 
    new BareJidComparer(), new MessageCB(MessageCallBack), null);

Now the MessageCallBack method is executed if a new message arrives:

static void MessageCallBack
    (object sender, agsXMPP.protocol.client.Message msg, object data)
{
    if (msg.Body != null)
    {                
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine("{0}>> {1}", msg.From.User, msg.Body);
        Console.ForegroundColor = ConsoleColor.Green;
    }
} 

Sending messages is quite an easy task:

xmpp.Send(new Message(new Jid(JID_Receiver), MessageType.chat, outMessage)); 

where the JID_Receiver is the JID object of our chat buddy. This code should be packed into a loop, to send more than one message (in the download example I have put it into a do loop, with the string q! as the exit criteria). When you are finished, you just need to close the XmppClientConnection object:

xmpp.Close();

Chat

That is all there is to creating a little Jabber Chat Client which looks like this:

Screenshot - JabberClient_Example.jpg

The corresponding screenshots of my chat partner using PSI:

Screenshot - JabberClient_Psi.jpg

Summary

There are plenty more features of Jabber/XMPP provided in the agsXMPP library, like creating your own Jabber server or creating your own packages. I think for an entry into Jabber development under C#, it is best to start with client development. The agsXMPP SDK provides a few very detailed examples like a Windows based mini client and a server component. If you would like to dive deeper into this technology, I suggest you study these examples before you dive into the libraries' source code.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Frank Mayer-Potschak
Software Developer FMP software & process engineering GmhH
Germany Germany
Im working as freelance consultant and software engineer in southern germany. If you have any questions about this article please contact me.

Comments and Discussions

 
QuestionGreat [modified] Pinmemberkhmesmer17-May-13 7:51 
QuestionHow to create External Component Client using the agsXMPP Library? PinmemberMember 1005665516-May-13 0:59 
QuestionNot able to configure openfire on local system Pinmembernitin_ion8-Mar-12 17:41 
Generalproblem Pinmembersonu tak4-Mar-11 18:10 
GeneralRe: problem Pinmembersenjougahara4-May-11 10:38 
QuestionCompared to Jabber.NET? Pinmemberdaluu16-May-10 18:13 
GeneralGreat article PinmemberNajeeb Shaikh15-Apr-10 21:08 
Generalconnect to sametime using agsXMPP Pinmemberscjwei18-Jan-09 2:52 
GeneralRe: connect to sametime using agsXMPP PinmemberFrank Mayer-Potschak20-Jan-09 1:30 
QuestionHow client deal with subscription PinmemberVS_Study25-Mar-08 16:05 
AnswerRe: How client deal with subscription Pinmemberjimu81305-Aug-08 17:20 
Questionxmpp Authenticated False ? False - wats wrong PinmemberAmitDey17-Feb-08 8:23 
GeneralRe: xmpp Authenticated False ? False - wats wrong PinmemberFrank Mayer-Potschak17-Feb-08 11:13 
GeneralRe: xmpp Authenticated False ? False - wats wrong PinmemberAmitDey18-Feb-08 3:01 
AnswerRe: xmpp Authenticated False ? False - wats wrong PinmemberAnuj39418-Mar-13 21:24 
Generalthis lib does not support through firewall PinmemberUnruled Boy8-Jan-08 3:33 
GeneralRe: this lib does not support through firewall PinmemberFrank Mayer-Potschak8-Jan-08 6:13 
GeneralRe: this lib does not support through firewall PinmemberUnruled Boy8-Jan-08 15:06 
GeneralRe: this lib does not support through firewall PinmemberFrank Mayer-Potschak9-Jan-08 5:21 
GeneralRe: this lib does not support through firewall PinmemberUnruled Boy9-Jan-08 14:57 
GeneralRe: this lib does not support through firewall PinmemberFrank Mayer-Potschak10-Jan-08 8:13 
GeneralRe: this lib does not support through firewall PinmemberUnruled Boy10-Jan-08 16:17 
GeneralRe: this lib does not support through firewall PinmemberFrank Mayer-Potschak10-Jan-08 20:41 
GeneralRe: this lib does not support through firewall PinmemberUnruled Boy10-Jan-08 21:10 
GeneralRe: this lib does not support through firewall PinmemberFrank Mayer-Potschak10-Jan-08 21:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140415.2 | Last Updated 12 Nov 2007
Article Copyright 2007 by Frank Mayer-Potschak
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid