gembin

          OSGi, Eclipse Equinox, ECF, Virgo, Gemini, Apache Felix, Karaf, Aires, Camel, Eclipse RCP

          HBase, Hadoop, ZooKeeper, Cassandra

          Flex4, AS3, Swiz framework, GraniteDS, BlazeDS etc.

          There is nothing that software can't fix. Unfortunately, there is also nothing that software can't completely fuck up. That gap is called talent.

          About Me

           

          用JAVA實(shí)現(xiàn)MSN Messenger的功能[zhuan]

          本文介紹了一個(gè)用Java編寫的可以訪問(wèn)MSN服務(wù)的開(kāi)發(fā)包-JMsn,利用這個(gè)開(kāi)發(fā)包你可以編寫自己的具有MSN Messenger功能的客戶端程序。

          現(xiàn)在的即時(shí)通訊軟件琳瑯滿 目,大家耳熟能詳?shù)臒o(wú)非就是騰訊公司的QQ,微軟公司的MSN Messenger以及網(wǎng)易的泡泡,就用戶量而言這三者應(yīng)該是名列前茅的。但是騰訊公司的QQ以及網(wǎng)易的泡泡由于并沒(méi)有公開(kāi)其客戶端與服務(wù)器之間的通訊協(xié) 議導(dǎo)致開(kāi)發(fā)者很難利用起這一龐大的用戶群體來(lái)開(kāi)辟另外的服務(wù)渠道。MSN Messenger這一由世界頭號(hào)軟件商-微軟公司開(kāi)發(fā)的即時(shí)通訊軟件,憑借其與windows操作系統(tǒng)和整個(gè)微軟產(chǎn)品家族的緊密結(jié)合,簡(jiǎn)單實(shí)用、性能穩(wěn) 定、世界通用等特點(diǎn),很快被中國(guó)用戶接受,目前其用戶正在以幾何數(shù)字增長(zhǎng)。但是讓開(kāi)發(fā)者雀躍的是該軟件同時(shí)也提供了開(kāi)放的API以及開(kāi)放的通訊協(xié)議。著名 的MSN Plus就是一款利用其API開(kāi)發(fā)的用于擴(kuò)展MSN Messenger功能的插件。而我們今天要介紹的jMSN則是封裝了MSN Messenger開(kāi)放的通訊協(xié)議的JAVA API,通過(guò)這個(gè)API開(kāi)發(fā)者完全可以使用JAVA語(yǔ)言模擬出MSN Messenger軟件,API的作者也提供一個(gè)用JAVA語(yǔ)言編寫的在某方面功能甚至比MSN Messenger還強(qiáng)大的MSN 客戶端軟件。由于采用了跨平臺(tái)的JAVA語(yǔ)言開(kāi)發(fā),因此該軟件也可同時(shí)運(yùn)行于其他操作系統(tǒng),目前已經(jīng)經(jīng)過(guò)測(cè)試的有各種Linux系統(tǒng)以及Mac OS上,當(dāng)然還有視窗操作系統(tǒng)。

          jMSN是一個(gè)韓國(guó)人開(kāi)發(fā)的開(kāi)放源碼的API,可以從 http://sourceforge.net/projects/jmsn/站點(diǎn)上下載,該項(xiàng)目的首頁(yè)基本上以韓文為主,包括它的API文檔的說(shuō)明都是 韓文。這個(gè)讓我非常頭疼,不過(guò)沒(méi)有關(guān)系,因?yàn)閖MSN非常簡(jiǎn)單,如果沒(méi)有什么特殊情況下不看那些說(shuō)明也沒(méi)有關(guān)系。jMSN的主頁(yè)中提供兩個(gè)部件供下載如下 圖所示,其中jmsn是一個(gè)完整的JAVA應(yīng)用程序,下載解壓后可以直接運(yùn)行,運(yùn)行的界面跟微軟的MSN Messenger很類似,包括操作上都非常一致,如果你的操作系統(tǒng)是Linux或者其他那都可以直接用它來(lái)替代微軟的程序。另外一個(gè)是msnm- lib,這個(gè)就是我們今天要介紹的API,它僅僅是一個(gè)開(kāi)發(fā)包,在jmsn組件中已經(jīng)包含了這個(gè)包。



          你 可能想先體驗(yàn)一下jmsn自帶的程序看看到底能完成什么樣的功能吧?解壓jmsn壓縮包后的目錄中會(huì)有一個(gè)可執(zhí)行文件,不過(guò)如果你的JDK不是使用安裝程 序安裝的,建議你不用執(zhí)行它,它會(huì)找不到j(luò)re的。你可以使用命令行來(lái)啟動(dòng)這個(gè)程序,這樣做有個(gè)好處是你還可以看到運(yùn)行中打印出來(lái)的信息。 啟動(dòng)jMSN的命令:java -jar jmsn.jar

          jMSN的登錄界面以及主窗口如下圖所示:





          應(yīng)該說(shuō)這個(gè)界面跟MSN Messenger是非常類似的。用戶可以通過(guò)它發(fā)送和接收消息等。在啟動(dòng)jMSN的命令行窗口中可以看到j(luò)MSN與服務(wù)器之間通訊的詳細(xì)信息。

          前 面我們主要在介紹jMSN大概的情況,介紹它能完成什么樣的功能。下面我們開(kāi)始來(lái)了解怎么利用jMSN自帶的API:msnm-lib來(lái)實(shí)現(xiàn)這些功能。下 圖是msnm-lib與jMSN包括MSN系統(tǒng)之間的關(guān)系,也就是說(shuō)我們可以通過(guò)msnm-lib來(lái)完成與MSN服務(wù)器之間的通訊而不需要我們?nèi)ゲ傩木唧w 的通訊協(xié)議的細(xì)節(jié)。事實(shí)上msnm-lib給我們做了更多的事情使得我們使用msnm-lib來(lái)開(kāi)發(fā)一個(gè)MSN應(yīng)用程序變得非常的簡(jiǎn)單,這也就是我前面提 到的我們完全可以不去可能它所提供的韓文API文檔的緣故,因?yàn)槭褂盟鼘?shí)在是太簡(jiǎn)單了。



          閩南語(yǔ)說(shuō):說(shuō)破不值錢!閑話說(shuō)了那么多,現(xiàn)在我們就開(kāi)始來(lái)開(kāi)發(fā)我們自己基于JAVA的跨平臺(tái)的MSN客戶端程序。相信聽(tīng)到這句大家都會(huì)覺(jué)得血脈膨脹,沒(méi)錯(cuò),還有什么比動(dòng)手寫程序更讓人興奮的事情呢?何況還是基于JAVA的、跨平臺(tái)的!

          我們先給出一段可運(yùn)行的代碼來(lái)完成一個(gè)最簡(jiǎn)單的功能:當(dāng)有人把它加入好友時(shí),程序自動(dòng)將之加入好友,當(dāng)有人給它發(fā)送信息,程序自動(dòng)回復(fù)一條相同的信息。OK,完成這么簡(jiǎn)單的功能的代碼如下:

          /*
          * Created on 2003-11-21 by Liudong
          */
          package jmsn.demo;
          import rath.msnm.MSNMessenger;
          import rath.msnm.SwitchboardSession;
          import rath.msnm.UserStatus;
          import rath.msnm.entity.MsnFriend;
          import rath.msnm.event.MsnAdapter;
          import rath.msnm.msg.MimeMessage;
          /**
          * MSN演示程序
          * @author Liudong
          */
          public class MSNDaemon extends Thread {
          private static MSNMessenger msn;
          public static void main(String[] args) {
          msn = new MSNMessenger("youraccount@hotmail.com", "password");
          msn.setInitialStatus(UserStatus.ONLINE);
          msn.addMsnListener(new MSNAdapter(msn));
          msn.login();
          System.out.println("Waiting for the response....");
          //捕捉Ctrl+C的輸入以便注銷MSN的登錄
          Runtime.getRuntime().addShutdownHook(new MSNDaemon());
          }
          /**
          * 用戶中止程序執(zhí)行
          */
          public void run() {
          msn.logout();
          System.out.println("MSN Logout OK");
          }
          }
          /**
          * MSN消息事件處理類
          * @author Liudong
          */
          class MSNAdapter extends MsnAdapter {
          MSNMessenger messenger;
          public MSNAdapter(MSNMessenger messenger) {
          this.messenger = messenger;
          }
          /**
          * 某人正在輸入信息
          */
          public void progressTyping(
          SwitchboardSession ss,
          MsnFriend friend,
          String typingUser) {
          System.out.println(friend.getLoginName() + "正在輸入信息...");
          }
          /**
          * 收到消息的時(shí)候執(zhí)行該方法
          */
          public void instantMessageReceived(
          SwitchboardSession ss,
          MsnFriend friend,
          MimeMessage mime) {
          System.out.print("接收到消息:" + friend.getFriendlyName() + "->");
          System.out.println(mime.getMessage());
          try {
          //發(fā)送相同的回復(fù)信息給發(fā)送者
          messenger.sendMessage(friend.getLoginName(), mime);
          } catch (Exception e) {
          e.printStackTrace();
          }
          }
          /**
          * 登錄成功后執(zhí)行該方法
          */
          public void loginComplete(MsnFriend own) {
          System.out.println(own.getLoginName() + " Login OK");
          }
          /**
          * 登錄失敗后執(zhí)行該方法
          */
          public void loginError(String header) {
          System.out.println("Login Failed: " + header);
          }
          /**
          * 好友離線時(shí)執(zhí)行該方法
          */
          public void userOffline(String loginName) {
          System.out.println("USER " + loginName + " Logout.");
          }
          /**
          * 好友上線時(shí)執(zhí)行該方法
          */
          public void userOnline(MsnFriend friend) {
          System.out.println("USER "+friend.getFriendlyName()+" Login.");
          }
          /**
          * 有人加我為好友時(shí)執(zhí)行
          */
          public void whoAddedMe(MsnFriend friend) {
          System.out.println("USER " + friend.getLoginName() + " Addme.");
          try {
          messenger.addFriend(friend.getLoginName());
          } catch (Exception e) {
          e.printStackTrace();
          }
          }
          /**
          * 有人把我從好友列表中刪除時(shí)執(zhí)行
          */
          public void whoRemovedMe(MsnFriend friend) {
          System.out.println("USER "+friend.getLoginName()+" Remove me.");
          try {
          messenger.removeFriend(friend.getLoginName());
          } catch (Exception e) {
          e.printStackTrace();
          }
          }
          }

          除了兩個(gè)常用的對(duì)象MsnFriend以及 MimeMessage分別用來(lái)表示我的好友以及MSN信息外,其他我們需要了解的也就是MSNMessenger以及MsnAdapter了。當(dāng)然了前 提是我們不需要除了聊天外的其他功能,例如文件傳輸?shù)鹊?。類MSNMessenger 對(duì)應(yīng)著一個(gè)帳號(hào)的一次登錄會(huì)話。我們僅僅是需要告訴MSNMessenger類我們登錄所用的帳號(hào)、密碼、登錄后的初始狀態(tài)以及我們?cè)趺磥?lái)處理從MSN服 務(wù)器上接收到的任何信息。在msnm-lib中,處理MSN信息是通過(guò)一個(gè)叫MsnAdapter類來(lái)處理的,這個(gè)類定義了如何處理例如收到消息、有人加 我為好友等等的事件,開(kāi)發(fā)者可以重載這些方法以便進(jìn)行自行處理。我們自行擴(kuò)展MsnAdapter的類必須告訴MSNMessenger實(shí)例知道,這也就 是我們前面代碼中的 msn.addMsnListener(new MSNAdapter(msn)); 自行擴(kuò)展MsnAdapter的類是用來(lái)處理被動(dòng)消息的,例如有人給我發(fā)消息等。當(dāng)我們要發(fā)送消息給別人的時(shí)候就需要用到MSNMessenger的實(shí) 例,這也就是我們?yōu)槭裁匆袽SNMessenger的實(shí)例傳遞給MSNAdapter的原因,因?yàn)楫?dāng)我們接收到任何消息時(shí)要給發(fā)送人回復(fù)一條相同的信 息。

          到此我們前面提出的簡(jiǎn)單功能已經(jīng)完成了,讀者可以在自己的機(jī)器上進(jìn)行測(cè)試,運(yùn)行時(shí)需要用到msnm-lib庫(kù),也就是msnm.jar文件。下圖是運(yùn)行時(shí)候的一個(gè)截圖:



          關(guān)于多人聊天:

          MSN 有另外一個(gè)不錯(cuò)的功能就是多人同時(shí)聊天,msnm-lib對(duì)這個(gè)功能支持也非常好。在MsnAdapter中定義的方法 instantMessageReceived的第一個(gè)參數(shù)類型為SwitchboardSession。當(dāng)接收到消息時(shí),我們可以從這個(gè)參數(shù)中獲取多人 聊天的一個(gè)會(huì)話標(biāo)識(shí),同時(shí)可以通過(guò)getMsnFriends來(lái)讀取參與當(dāng)前聊天的所有好友。當(dāng)你要主動(dòng)發(fā)送消息的時(shí)候你就必須從 SwitchboardSession中讀取所有的好友并給他們一一發(fā)送信息。

          關(guān)于文件傳輸:

          可 能這是我發(fā)現(xiàn)的關(guān)于msnm-lib的唯一不足,或者說(shuō)還不夠完善的部分。經(jīng)過(guò)測(cè)試發(fā)現(xiàn)使用微軟的MSN程序可以正常傳輸文件的兩臺(tái)機(jī)器用jMSN卻無(wú)法 傳輸,錯(cuò)誤信息都是說(shuō)連接超時(shí),這兩臺(tái)機(jī)器不在同一個(gè)子網(wǎng)。相信msnm-lib對(duì)這個(gè)功能并沒(méi)有進(jìn)行處理。由于并沒(méi)有兩臺(tái)直接連接Internet的機(jī) 器,因此關(guān)于jMSN的文件傳輸一直都沒(méi)有辦法來(lái)做一個(gè)試驗(yàn),希望新版本的msnm-lib能解決好這個(gè)問(wèn)題。

          總結(jié):

          盡 管在文件傳輸上有點(diǎn)瑕疵,但是msnm-lib所提供的功能已經(jīng)非常棒了,至少在我第一眼看到它的時(shí)候心里說(shuō):沒(méi)錯(cuò),這就是我想要的東西!本文旨在介紹如 何使用msnm-lib來(lái)完成一個(gè)簡(jiǎn)單的MSN客戶端,至于如果讓它在實(shí)際的應(yīng)用系統(tǒng)中發(fā)揮作用,讀者們肯定有比我更多的想法,比如說(shuō)是否可以利用它來(lái)豐 富客服的渠道等等,當(dāng)然這些都超過(guò)我們的題目。如在使用中發(fā)現(xiàn)任何問(wèn)題,歡迎來(lái)信共同研究。



          參考資料

          jMSN網(wǎng)址(韓文) http://jmsn.sourceforge.net/

          posted on 2008-04-22 18:25 gembin 閱讀(1009) 評(píng)論(0)  編輯  收藏 所屬分類: JavaSE

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(6)

          隨筆分類(440)

          隨筆檔案(378)

          文章檔案(6)

          新聞檔案(1)

          相冊(cè)

          收藏夾(9)

          Adobe

          Android

          AS3

          Blog-Links

          Build

          Design Pattern

          Eclipse

          Favorite Links

          Flickr

          Game Dev

          HBase

          Identity Management

          IT resources

          JEE

          Language

          OpenID

          OSGi

          SOA

          Version Control

          最新隨筆

          搜索

          積分與排名

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          free counters
          主站蜘蛛池模板: 莱阳市| 宁陵县| 安岳县| 固安县| 大名县| 吉安市| 明光市| 莎车县| 水城县| 苗栗县| 杭州市| 安陆市| 双桥区| 民乐县| 舟山市| 阿鲁科尔沁旗| 阿拉善左旗| 嘉兴市| 怀远县| 文水县| 搜索| 抚顺市| 太原市| 桐梓县| 应城市| 南宫市| 名山县| 临朐县| 策勒县| 莱阳市| 鄂尔多斯市| 定兴县| 永兴县| 青铜峡市| 高安市| 汉寿县| 武隆县| 明星| 繁昌县| 南阳市| 双牌县|