Click here to Skip to main content
15,867,834 members
Articles / Programming Languages / C#
Article

Creating a Jabber Client using the agsXMPP Library

Rate me:
Please Sign up or sign in to vote.
4.98/5 (30 votes)
11 Nov 2007CPOL6 min read 275.9K   13.9K   104   45
This article describes how to create a small Jabber Chat client.

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:

XML
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:

C#
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:

C#
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:

C#
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:

C#
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:

C#
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:

C#
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:

C#
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:

C#
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.

C#
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:

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

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

C#
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:

C#
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:

C#
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)


Written By
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

 
QuestionLogin Failed Pin
Member 1343456527-Sep-17 22:41
Member 1343456527-Sep-17 22:41 
GeneralMy vote of 1 Pin
Carl Edwards In SA27-Nov-16 19:20
professionalCarl Edwards In SA27-Nov-16 19:20 
QuestionReading all incoming Messages Pin
Member 415698231-Aug-15 22:33
Member 415698231-Aug-15 22:33 
QuestionWindows service Pin
Member 944271729-May-15 8:17
Member 944271729-May-15 8:17 
QuestionNoWorking with IP address. Pin
Member 778923925-May-15 21:58
Member 778923925-May-15 21:58 
QuestionIt's not free!!! Pin
ayseff10-May-15 7:28
ayseff10-May-15 7:28 
QuestionHow To send XML Request to XMPP server (Without matrix) Pin
ivasu5-Sep-14 19:16
ivasu5-Sep-14 19:16 
SuggestionHow to connect to a Google AppDomain? Here is the answer Pin
parmando10-Jul-14 10:54
parmando10-Jul-14 10:54 
QuestionGreat Pin
khmesmer17-May-13 7:51
khmesmer17-May-13 7:51 
QuestionHow to create External Component Client using the agsXMPP Library? Pin
Member 1005665516-May-13 0:59
Member 1005665516-May-13 0:59 
QuestionNot able to configure openfire on local system Pin
nitin_ion8-Mar-12 17:41
nitin_ion8-Mar-12 17:41 
Generalproblem Pin
sonu tak4-Mar-11 18:10
sonu tak4-Mar-11 18:10 
GeneralRe: problem Pin
senjougahara4-May-11 10:38
senjougahara4-May-11 10:38 
QuestionCompared to Jabber.NET? Pin
daluu16-May-10 18:13
daluu16-May-10 18:13 
GeneralGreat article Pin
Najeeb Shaikh15-Apr-10 21:08
Najeeb Shaikh15-Apr-10 21:08 
Great article, Frank!

One query though, I am trying to implement RPC using the agsXMPP library (XEP-0009: Jabber-RPC), something like this:

agsXMPP.protocol.iq.rpc.MethodCall methodCall = new agsXMPP.protocol.iq.rpc.MethodCall ("DoSomething", null);
_connection.Send (methodCall);

However, for the life of me I am not able to figure out how to direct this RPC call to a particular client... the MethodCall class does not have a "To" property. Can you tell me what I am missing?

Thanks in advance!
~Najeeb (www.CodeMinima.com)
Najeeb Shaikh

Generalconnect to sametime using agsXMPP Pin
scjwei18-Jan-09 2:52
scjwei18-Jan-09 2:52 
GeneralRe: connect to sametime using agsXMPP Pin
Frank Mayer-Potschak20-Jan-09 1:30
Frank Mayer-Potschak20-Jan-09 1:30 
QuestionHow client deal with subscription Pin
VS_Study25-Mar-08 16:05
VS_Study25-Mar-08 16:05 
AnswerRe: How client deal with subscription Pin
oceanchow5-Aug-08 17:20
oceanchow5-Aug-08 17:20 
Questionxmpp Authenticated False ? False - wats wrong Pin
AmitDey17-Feb-08 8:23
AmitDey17-Feb-08 8:23 
GeneralRe: xmpp Authenticated False ? False - wats wrong Pin
Frank Mayer-Potschak17-Feb-08 11:13
Frank Mayer-Potschak17-Feb-08 11:13 
GeneralRe: xmpp Authenticated False ? False - wats wrong Pin
AmitDey18-Feb-08 3:01
AmitDey18-Feb-08 3:01 
AnswerRe: xmpp Authenticated False ? False - wats wrong Pin
Anuj39418-Mar-13 21:24
Anuj39418-Mar-13 21:24 
GeneralRe: xmpp Authenticated False ? False - wats wrong Pin
Wiktor Tytkowski3-May-16 4:11
Wiktor Tytkowski3-May-16 4:11 
Generalthis lib does not support through firewall Pin
Huisheng Chen8-Jan-08 3:33
Huisheng Chen8-Jan-08 3:33 

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

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