Build an MSN robot platform with C #

Source: Internet
Author: User

As MSN itself is open-source, it is possible to develop various plug-ins or applications based on it.

This article aims to design and demonstrate how to use. Net to build a public MSN platform. Its basic functions include:

 

1. Provides an MSN robot publishing interface, which can be used by any user to send information to other contacts.

2. Provides an MSN publishing interface, which can be used to publish your own MSN information.

 

Of course, this platform can also expand its functions based on the support of the MSN protocol.

 

For ease of use, our interfaces use WebService. Here, we will not go into detail about WebService applications.

 

Next we will mainly discuss the technical selection and logic process of our MSN application:

 

Protocol-based development requires a lot of work. I chose the already mature dotmsn1.2 component developed by a Finnish user (the latest version is 2.0, But it seems complicated, and I will no longer use it, interested readers can study it ). It provides C # basic encapsulation of the MSN protocol.

 

From protocol-level analysis, there are a total of the following processes for MSN from login to message sending:

 

Login-connection-synchronization-wait for synchronization to complete-create session-invite contacts-wait for connection to succeed-wait for invitation to succeed-send

 

Every step in this process may be abnormal, so a robust error handling program is required. The logical process I have built mainly includes the following:

 

1. MSN connection cache. (You can build Multiple Robot instances and provide cache pool hosting)

2. Session buffer pool. (Various sessions are managed during the actual operation of MSN)

3. Reclaim connections. (If there are no tasks for a long time, the MSN robot will automatically recycle them. Of course, this is transparent to users)

4. Security of task queues and multithreading. (In actual operation of the platform, multi-thread concurrent access may occur. Therefore, task queue management and multi-thread security are provided for each connected instance)

 

Let's take a look at the Code:

 

MSN machine human

 

Main ideas:

Each robot maintains a thread used for task training and execution (see the start function ).

Each robot maintains a task queue (queue <msntask> _ tasks) and a session Buffer Pool (see the getconversationhandler function ).

Maintain error handling in each logic step to ensure that the task can be executed as successful as possible.

Using system; <br/> using system. collections. generic; <br/> using system. collections; <br/> using system. LINQ; <br/> using system. text; <br/> using system. threading; <br/> using system. io; </P> <p> using dotmsn; </P> <p> namespace msnplatform <br/>{< br/> public class msnrobot <br/>{< br/> # region const <br/> string _ User = string. empty; <br/> string _ password = string. empty; </P> <p> const int connect_inteval = 15000; // connection Retry Interval <br/> const int command_inteval = 1000; // Retry Interval of local commands <br/> const int check_task_interval = 4000; // sending task detection interval <br/> const int max_err_count = 10; // maximum number of errors <br/> const int max_no_task_count = 300; // The maximum number of robot inspections to be destroyed (if no task exists) <br/> const int add_user_want_turn = 5; // Add contacts or synchronize the number of waiting rounds <br/> const int add_user_fail_count = 4; // number of failed contact addition Times <br/> const int max_reconnect_times = 10; // maximum number of Retries for creating a session <Br/> const int reconnect_consation_turn = 8; // number of times the session connection is re-created <br/> # endregion </P> <p> Public msnrobot (string user, string password) <br/>{< br/> _ User = user; <br/> _ password = password; <br/> Init (); <br/>}</P> <p> Public void Init () <br/>{< br/> conversationmapping = new hashtable (); <br/> thread robotthread = new thread (New threadstart (this. start); <br/> robotthread. start (); <br/>}</P> <p> mess Enger messenger = NULL; <br/> private bool _ isconnected = false; // identifies whether a connection is established. <br/> private bool _ issynchronized = false; // whether to synchronize <br/> private bool connect () <br/>{< br/> try <br/>{< br/> logger. log ("connecting to the server .. "); </P> <p> messenger = new messenger (); // instantiate the MSN class <br/> messenger. conversationcreated + = new messenger. conversationcreatedhandler (conversationcreated); <br/> messenger. synchronizationcompleted + = New messenger. synchronizationcompletedhandler (onsynchronizationcompleted); // synchronous user list callback <br/> messenger. connect (_ User, _ password); // connect to the server (blocking) <br/> logger. log ("OK"); <br/> messenger. synchronizelist (); // start synchronization <br/> return true; <br/>}< br/> catch (exception e) <br/>{< br/> logger. log ("connection exception" + E. tostring (); <br/> return false; <br/>}</P> <p> private void connectandsynchronize () <br/> {<br /> Conversationmapping. clear (); // clear session ing <br/> while (this. connect () = false) // connect to the server <br/>{< br/> thread. sleep (connect_inteval); <br/>}</P> <p> private void conversationcreated (messenger sender, conversationeventargs E) // callback for successful connection <br/>{< br/> logger. log ("session established successfully"); <br/> _ isconnected = true; <br/> E. conversation. messagereceived + = new conversation. messagereceivedhandler (messagereceived); <BR/>}</P> <p> // processing function when receiving a contact message <br/> private void messagereceived (conversation sender, messageeventargs E) <br/>{< br/> string MSG = E. message. text; <br/> logger. log (E. sender. name + "said:" + MSG); <br/> sender. sendmessage ("Don't send messages to me, it doesn't make any sense"); <br/>}</P> <p> private void onsynchronizationcompleted (messenger sender, eventargs E) <br/> {<br/> logger. log ("synchronization completed"); <br/> messenger. setstatus (msnstatus. online ); <Br/> _ issynchronized = true; <br/>}</P> <p> private hashtable conversationmapping = NULL; <br/> private int errcount = 0; <br/> private conversation getconversationhandler (string ADDR, bool isforcereconnect) <br/>{< br/> try <br/>{< br/> If (conversation) (conversationmapping [ADDR]) = NULL | isforcereconnect) <br/> {<br/> conversationmapping [ADDR] = messenger. requestconversation (ADDR); <br />}< Br/> return (conversation) (conversationmapping [ADDR]); <br/>}< br/> catch (exception E) <br/> {<br/> logger. log ("session creation exception" + E. tostring (); <br/> return NULL; <br/>}</P> <p> // <summary> <br/> // main MSN Worker Process <br/> // /</Summary> <br/> private void start () <br/>{< br/> bool reconnectflag = true; // reconnecting server flag <br/> int notask = 0; // no task Statistics <br/> while (true) // send task <br/>{< br/> If (recon Nectflag) // reconnect to the server <br/>{< br/> errcount = 0; <br/> reconnectflag = false; <br/> connectandsynchronize (); <br/>}</P> <p> thread. sleep (check_task_interval); // wait interval <br/> lock (this) <br/>{< br/> try <br/>{< br/> If (_ tasks. count> 0) // The task queue is not empty <br/>{< br/> notask = 0; // clear the task without a task tag <br/> msntask task = _ tasks. dequeue (); // obtain a task <br/> conversation con = This. getconversationhandler (task. ADDR, false ); // Create a session <br/> logger. log ("START task contact =" + task. ADDR + ", information =" + task. MSG); <br/> If (con! = NULL & con. connected) // if the session has been connected <br/>{< br/> If (task. status = msntaskstatus. ready) // is the preparation task <br/>{< br/> If (con. invited) // if the session has been invited <br/>{< br/> task. status = msntaskstatus. doing; <br/> logger. log (task. ADDR + "Invitation successful, send"); <br/> con. sendmessage (task. MSG); // send the message <br/>}< br/> else // otherwise, the session is invited (possibly 1. this user is not a contact. the session has not been established successfully.) <br/>{< br/> task. status = msntaskstatus. adding; <br/> logger. log (task. ADDR + "Inviting .. "); <br/> messenger. addcontact (task. ADDR); // Add as contact <br/> If (++ task. addturn <add_user_fail_count) // if it is less than the number of times that the added contact has exceeded <br/> _ tasks. enqueue (task); // put the task back to the end <br/> else <br/> logger. log ("add contact timeout, discard task"); </P> <p> task. waitturn = add_user_want_turn; <br/> messenger. synchronizelist (); // start synchronization <br/>}< br/> else if (task. status = msntaskstatus. adding) // adding a contact or waiting for synchronization <br/>{< br/> _ tasks. enqu EUE (task); // put the task back to the end <br/> If (-- task. waitturn <= 0) <br/> task. status = msntaskstatus. ready; <br/>}< br/> errcount = 0; // once successful, number of errors cleared <br/>}< br/> else if (con = NULL) <br/>{< br/> logger. log ("task failed"); <br/> task. status = msntaskstatus. fail; <br/>}</P> <p> If (! Con. connected) // not connected <br/>{< br/> logger. log ("not connected, waiting for connection .. "); </P> <p> If (task. reconnect! = 0 & task. reconnect % reconnect_consation_turn = 0) <br/>{< br/> logger. log ("session connection establishment timeout, re-establish"); <br/> This. getconversationhandler (task. ADDR, true); <br/>}< br/> If (++ task. reconnect <= max_reconnect_times) <br/>{< br/> _ tasks. enqueue (task); <br/>}< br/> else <br/>{< br/> errcount ++; <br/> logger. log ("failed session connection establishment times exceed the limit, discard the task "); <br/>}< br/> else <br/>{< br/> notask ++; <br/> If (notask> max_no_task_count) // destroy the robot <br/>{< br/> logger. log ("No tasks for a long time, temporarily destroy robots"); <br/> msnrobotfactory. unregist (_ User); <br/> break; <br/>}< br/> catch (exception E) <br/> {<br/> errcount ++; // The number of errors increases. <br/> logger. log ("exception" + E. tostring (); <br/>}< br/> finally <br/>{< br/> If (errcount> max_err_count) // The error count is full, reconnect to the server <br/>{< br/> logger. log ("error accumulative full, reconnect to the server"); <br/> reconnectflag = true; <br/>}</P> <p> queue <msntask> _ tasks = new queue <msntask> (); </P> <p> /// <summary> <br/> // Add a sending task. <br/> /// </Summary> <br/> // /<Param name = "ADDR"> send to email address </param> <br/> // <Param name = "MSG"> send content </param> <br/> Public int addtask (string ADDR, string MSG) <br/>{< br/> return this. addtask (New msntask (ADDR, MSG )); <br/>}</P> <p> // <summary> <br/> // Add a task <br/> /// </Summary> <br />/// <Param name = "task"> </param> <br/> Public int addtask (msntask task) <br/>{< br/> lock (this) <br/>{< br/> logger. log ("add task ADDR =" + task. ADDR + ", MSG =" + task. MSG); <br/> _ tasks. enqueue (task); <br/>}< br/> return task. ID; <br/>}< br/>

 

MSN robot task

 

Main ideas:

Task execution uses the state machine

 

Using system; <br/> using system. collections. generic; <br/> using system. LINQ; <br/> using system. text; </P> <p> namespace msnplatform <br/> {<br/> Public Enum msntaskstatus {ready, doing, fail, success, adding, connecting} </P> <p> public class msntask <br/> {<br/> Public msntask (string ADDR, string MSG) <br/>{< br/> ADDR = ADDR; <br/> MSG = MSG; <br/> Status = msntaskstatus. ready; <br/> This. id = idcount ++; <br/> addturn = 0; <br/> waitturn = 0; <br/> reconnect = 0; <br/>}</P> <p> Private Static int idcount = 1; // task id counter </P> <p> internal string ADDR {Get; set ;} <br/> internal string MSG {Get; Set ;}< br/> internal msntaskstatus status {Get; Set ;}</P> <p> Public int ID {Get; set ;}</P> <p> Public int waitturn {Get; Set ;}< br/> Public int addturn {Get; set ;} <br/> Public int reconnect {Get; Set ;}< br/>}< br/>

 

MSN Robot Factory

 

Main ideas:

Maintain the MSN connection Buffer Pool

 

Using system; <br/> using system. data; <br/> using system. configuration; <br/> using system. LINQ; <br/> using system. web; <br/> using system. web. security; <br/> using system. web. ui; <br/> using system. web. UI. htmlcontrols; <br/> using system. web. UI. webcontrols; <br/> using system. web. UI. webcontrols. webparts; <br/> using system. XML. LINQ; <br/> using system. collections; </P> <p> namespace msnplatform <br/>{< br/> public class msnrobotfactory <br/>{< br/> static private hashtable userhandlermapping = new hashtable (); <br/> static public msnrobot getrobot (string user, string PW) <br/>{< br/> If (userhandlermapping [user] = NULL) <br/>{< br/> userhandlermapping [user] = new msnrobot (user, PW); <br/>}< br/> return (msnrobot) (userhandlermapping [user]); <br/>}</P> <p> static public void unregist (string user) <br/>{< br/> userhandlermapping. remove (User); <br/>}< br/>

 

Final Effect

 

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.