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

Connecting to MSN messenger with the MSNP9 protocol

Rate me:
Please Sign up or sign in to vote.
4.34/5 (34 votes)
4 Nov 20035 min read 506.7K   1.2K   103   56
This article explains how you can connect to MSN using the MSNP9 protocol. It also refers to another article I wrote.

Introduction

MSN messenger is a well known program. It lets you communicate with other users through Instant Messaging. Some people like to write their own MSN messenger, so that they can make some own adjustments and cool features. I have written, together with another student, our own MSN client in C#.  Recently Microsoft no longer supported protocols below MSNP 8. So I had to adjust our program to use MSNP9 (it used MSNP7).

After I have posted an earlier article about MSN, people asked me to give some more information on how to connect to the MSN servers.

So with this little article I would like to explain how you can connect to MSN with the use of the MSNP9 protocol. This article tells you what commands you have to send, and how to react to it. It uses an article that I have posted before. You can find it here.

Using the code

You can use this code in your own program, or you can look and see how you can connect to MSN in C#. The demo programs shows how you can use the following code.

What do we need?

First we use a separate class that will connect to the MSN server. We call it MSNConnection. Next we build another class that handles the commands that we receive from the servers, lets call this class ServerCommand.

Next we need to declare some variables that we will use in the class MSNConnection.

C#
private long            _transactionID = 0;
private TcpClient       _socket;
private NetworkStream   _stream;
private StreamReader    _reader;
private StreamWriter    _writer;

The transactionID is sent with almost every message that we send (also in chat sessions). The _reader and _writer are the streams from the socket.

Now we have the above, let's define some functions that will do the work for us. First we need to initialize the socket and StreamReaders.

C#
_transactionID = 0;
_socket = new TcpClient(host, port);
_stream = _socket.GetStream();
_reader = new StreamReader(_stream, Encoding.ASCII);
_writer = new StreamWriter(_stream, Encoding.ASCII);
_writer.AutoFlush = true;

We call this function ConnectSocket and it takes two parameters (host and port). Every time we make a new connection the transactionId is set to zero. If we make a function that creates the socket, why not make a function that closes the socket. Let's call it dispose.

C#
if( _socket != null )
{
    _reader.Close();
    _writer.Close();
    _stream.Close();
    _socket.Close();
    _socket = null;
}

We are making functions that read and write to the StreamReader and StreamWriter. First we define the StreamWriter. We then make a function that builds the string: WriteCommand. It takes 3 parameters: first is the command to send, next the parameters and last the option to leave the transactionId out.

C#
string line;
// check what type of format it should be
if (bSendId) 
    line = string.Format("{0} {1} {2}", command, _transactionID, parameters);
else
    line = string.Format("{0} {1}", command, parameters);
// Write the line
WriteLine(line, true);

The function WriteLine eventually writes the string to the StreamWriter. This function has two parameters first is the entire string and next is the option to send only a string and no end character.

C#
if (writeNewLine)
    _writer.WriteLine(line);
else
    _writer.Write(line);
// raise the transactionId
_transactionID++;

We have defined some writing functions. We also need to read the information. Let's call this function ReadCommand. This function reads from the reader, if there is nothing in the socket then makes an empty ServerCommand, else we make a ServerCommand with the given response.

C#
string  line = _reader.ReadLine();
Console.WriteLine("Reading: " + line);
if (line == null) 
{
    Console.WriteLine("Nothing received");
    return new ServerCommand();
}
else
{
    return new ServerCommand(line);
}

You noticed that I use the ServerCommand object. Lets look at the ServerCommand class.

C#
private string _cmdID;
private string _line;
private string[] _params;

public ServerCommand(string line)
{
    _line = line;
    // always 3 characters command
    _cmdID = line.Substring(0, 3);
    if (!(_cmdID == "QNG"))
    {
        _params = line.Substring(4).Split(' ');
    }
}

public ServerCommand()
{
    _line = "";
    _cmdID = "ERROR";
}

If we use the constructor with a valid line, then we will get a ServerCommand with the right information. If we get a QNG command then there will be no parameters. The command is always a three letter combination. If we use the constructor with no string, then the program knows that there is something wrong.

The other functions are used for retrieving the data from this class.

C#
public string CommandName
{
    get { return _cmdID; }
}

public string Param(int index)
{
    return _params[index];
}

Now all the functions are explained above, we can make the Connect function. This function needs two parameters: first is a valid username that has a passport, next is the password for that username.

First we are going to connect to the server.

C#
string  host = "messenger.hotmail.com"; 
int port = 1863;

ConnectSocket(host, port);

Now we are going to write the server commands, the first command we are going to write is the VER command. This command indicates what protocol we are using. We are using protocol MSNP9. We read the result in a new ServerCommand Object.

C#
ServerCommand ServCom

WriteCommand("VER", "MSNP9 CVRO", true); 
ServCom = ReadCommand();

Next we are going to check if we received the right information, if not then exit this function.

C#
if (ServCom.CommandName != "VER")
{
    return 1;
}

Now we have to send the CVR command, the parameters are the same like a real MSN messenger client. The server will response with a CVR command and a download place where you can get a newer MSN messenger, we just ignore this.

C#
WriteCommand("CVR", 
  "0x0409 win 4.10 i386 MSNMSGR 5.0.0544 MSMSGS " + UserName, true);
ServCom = ReadCommand(); 

After this is successful, we send de USR command with a TWN parameter and your username. TWN stands for TWEENER, this is based on the passport authentication.

C#
WriteCommand("USR", "TWN I " + UserName, true);
ServCom = ReadCommand();

If the command was not the USR command, it was probably the XFR command, this indicates to us that we have to transfer to another server. In the result is the new host and port, parse it.

C#
string[] arIP = ServCom.Param(2).Split(':');
host = arIP[0];
port = int.Parse(arIP[1]);

Now disconnect and connect again using the new host and port.

Dispose();

We were operating in a while loop, so the connect sequence starts again. You have to send all the commands again, but this time it is to another server.

If the responsecommand is USR then we are going to connect to this server. The response will hold a ChallengeString, we need this ChallengeString to get a valid ClientTicket.

C#
if (ServCom.CommandName == "USR")
{
    ChallengeString = ServCom.Param(3);
    break;
}

With the given ChallengeString we will get a valid clientticket.

C#
string clientticket = GetClientTicket(UserPassword, 
                                   UserName, ChallengeString);

This step is a rather large step. I have already wrote an article on this part, read all about it right here.

Finally now we have a ticketID, send it to the server.

C#
WriteCommand("USR", "TWN S " + clientticket, true);
ServCom = ReadCommand();

If we are in luck, we get the USR |transid| OK message. This indicates that we have successfully connected to the MSN servers.

Let's get our username and our screen name, this information was send together with de USR command.

C#
_UserName = ServCom.Param(2);
_ScreenName = ServCom.Param(3);

Last we are going to notify that we are going online, you can put a number of initial status messages here. NLN just means "Online", the rest are:

  • BSY - Busy
  • IDL - Idle
  • BRB - Be Right Back
  • AWY - Away
  • LUN - Out to Lunch
  • PHN - On the Phone
  • FLN - Offline
  • HDN - Hidden
WriteCommand("CHG", "NLN", true);

Now you are connected and everybody who have you in their list will see you online.

Right now, you have to get all the contacts, but that part is too big to explain right here.

Conclusion

Connecting to a MSN server is not that hard, you have to understand what to send and how to reply. Hopefully you have liked this article, so maybe now you want to write your own MSN messenger program.

Good luck!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior) Traxion
Netherlands Netherlands
I am 27 year and live in the Netherlands. I have graduated in 2004, for the study Computer Science. After my study I have started working as a Technical Consultant in the Identity & Access management branch (http://www.traxion.com).

I have acquired my MCSE and MCSD certifications. Currently I developing a lot of cool things in .NET & Java, I'm also upgrading my certifications to .NET 2.0.

I am the main programmer for the product that we are developing within our company it's called the IM Sequencer (Formally known as the MIIS Sequencer). This product enables users to control the execution from the management agents in MIIS (Microsoft Identity Integration Server) or as it is called now ILM 2007 (Identity Lifecycle Manager 2007) it also generates extensive reports that contains all the results from the management agents that enables administrators to easily track down errors or failures.

Check out the products website http://www.traxionsolutions.com/imsequencer. There are allot of cool features implemented, is uses WMI to connect and communicate with MIIS \ ILM, threading to execute multiple agents, XSLT for reporting transformation, XML for configuration, WinForms for displaying and Win Service for the scheduler engine, very cool!

You can reach me at paul.wijntjes@gmail.com

Comments and Discussions

 
Question这个还能用?是不是MSN 协议已经变了? Pin
Joson Jiang29-Apr-10 16:40
Joson Jiang29-Apr-10 16:40 
GeneralUnknown error occured while connecting... Pin
Baeltazor5-Feb-10 2:14
Baeltazor5-Feb-10 2:14 
GeneralRe: Unknown error occured while connecting... Pin
Paul Wijntjes (dominion99)9-Feb-10 19:34
Paul Wijntjes (dominion99)9-Feb-10 19:34 
GeneralRe: Unknown error occured while connecting... Pin
Kreion14-Feb-10 1:58
Kreion14-Feb-10 1:58 
GeneralRe: Unknown error occured while connecting... Pin
Wallkysek1-May-12 9:06
Wallkysek1-May-12 9:06 
Generalcomplete project Pin
Wrangly15-Oct-08 22:56
Wrangly15-Oct-08 22:56 
GeneralRetrieve Contact List Pin
Sebouh18112-Sep-07 23:15
Sebouh18112-Sep-07 23:15 
GeneralRe: Retrieve Contact List Pin
Paul Wijntjes (dominion99)1-Oct-07 0:02
Paul Wijntjes (dominion99)1-Oct-07 0:02 
QuestionRe: Retrieve Contact List Pin
Gazeebo25-Mar-09 13:53
Gazeebo25-Mar-09 13:53 
QuestionStatus not seen by others? Pin
Sebouh18112-Sep-07 22:06
Sebouh18112-Sep-07 22:06 
AnswerRe: Status not seen by others? Pin
Paul Wijntjes (dominion99)30-Sep-07 23:59
Paul Wijntjes (dominion99)30-Sep-07 23:59 
GeneralNice work Pin
HankiDesign6-Jul-07 8:27
HankiDesign6-Jul-07 8:27 
GeneralContact list Pin
ErickJackob18-Apr-07 20:40
ErickJackob18-Apr-07 20:40 
GeneralCreate you own Messenger in .NET Pin
skcrpk22-Oct-06 15:16
skcrpk22-Oct-06 15:16 
Generaldoes any body knows... Pin
b_panic28-Feb-06 13:41
b_panic28-Feb-06 13:41 
GeneralChange in code Pin
Paul Wijntjes (dominion99)24-Jan-06 1:13
Paul Wijntjes (dominion99)24-Jan-06 1:13 
JokeRe: Change in code Pin
Fyska8731-Dec-06 11:22
Fyska8731-Dec-06 11:22 
GeneralRe: Change in code Pin
script_man14-May-07 2:47
script_man14-May-07 2:47 
GeneralVOIP recorder Pin
triplebit4-Jan-06 8:05
triplebit4-Jan-06 8:05 
GeneralRecording Transmited Voice Pin
triplebit4-Jan-06 7:51
triplebit4-Jan-06 7:51 
work on VOIP recording software - on the transmitter part.
I can easily record most voip applications since they all use DirectSHow.
Since DitectShow capturing doesn't implement a special capture filter but
use classic multimedia functions, I simply hook these functions and
implement my own recording.
Problem is with MSN Messenger (and also Windows Messenger) which implement
something else. It uses waveInOpen only for query, and I don't know how to
trace the blocks being sent to the other side.
I saw somewhere (probably in this group) that its using full-duplex com
object, but this information
doesn't help me, since it doesn't exports any helpful function for hooking.

Does anyone have some experience with that and/or can some suggestions?

Regards

Kalish


GeneralNice but... Pin
Super Lloyd6-Dec-05 1:45
Super Lloyd6-Dec-05 1:45 
GeneralRe: Nice but... Pin
Paul Wijntjes (dominion99)6-Dec-05 21:58
Paul Wijntjes (dominion99)6-Dec-05 21:58 
GeneralRe: Nice but... Pin
Super Lloyd7-Dec-05 10:41
Super Lloyd7-Dec-05 10:41 
General.NET Messenger library Pin
Bas G3-May-05 5:55
sussBas G3-May-05 5:55 
GeneralRe: .NET Messenger library Pin
Huisheng Chen3-May-05 23:04
Huisheng Chen3-May-05 23:04 

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.