寫在前面
友情提示:在著手基于MobileIMSDK開發(fā)自已的即時(shí)通訊應(yīng)用前,建議以Demo工程為腳手架,快速上手MobileIMSDK!
Demo工程主要用于演示SDK的API調(diào)用等,它位于SDK完整下載包的如下目錄:

如上圖目錄demo_src/Server/所示,這是一個(gè)完整的Eclipse工程(含完整的可運(yùn)行Demo源碼)。
如果你只是想看看Demo的話,可以下載編譯好的Demo包立即體驗(yàn):它位于SDK完整下載包的?demo_binary/server/?目錄下。
第一部分:集成準(zhǔn)備
第1步:下載SDK并找到lib包
①?馬上下載:
最新版打包下載?點(diǎn)此進(jìn)入,或者前往?MobileIMSDK的Github自行同步代碼。
②?找到lib包:
位于SDK完整下載包的?sdl_binary/Server/?目錄下:

第2步:引用lib包和依賴庫(kù)
提示:MobileIMSDK的Server端lib包支持Java 1.7(含)及以上版本。
2.1 引用lib包(IDEA工程,本地jar方式)
①?IDEA中如何引用第3方本地jar包?
跟所有Java工程一樣引用jar包很簡(jiǎn)單,如果沒試過,請(qǐng)查看:IDEA引入本地jar包的兩種方法?或自行百度查找資料。
②?以MobileIMSDK Server的Demo工程為例,結(jié)果如下圖:

2.2 引用lib包(IDEA工程,Maven方式)
①?IDEA中如何在pom.xml中引用本地jar包和依賴庫(kù)?
在pom.xml加入以下配置:(以下配置參考自IM產(chǎn)品?RainbowChat)
<dependencies>
??<!-- 依賴的開源JSON庫(kù)Gson -->
??<dependency>
????<groupId>com.google.code.gson</groupId>
????<artifactId>gson</artifactId>
????<version>2.8.9</version>
??</dependency>
??<!-- 依賴的log4j日志框架的實(shí)用組合 -->
??<dependency>
????<groupId>org.apache.logging.log4j</groupId>
????<artifactId>log4j-api</artifactId>
????<version>2.23.1</version>
??</dependency>
??<dependency>
????<groupId>org.apache.logging.log4j</groupId>
????<artifactId>log4j-core</artifactId>
????<version>2.23.1</version>
??</dependency>
??<dependency>
????<groupId>org.apache.logging.log4j</groupId>
????<artifactId>log4j-slf4j-impl</artifactId>
????<version>2.23.1</version>
??</dependency>
??<!-- 依賴的RabbitMQ中間件的java客戶端庫(kù),用于與MobileIMSDK-Web產(chǎn)品進(jìn)行消息互通時(shí) -->
??<dependency>
????<groupId>com.rabbitmq</groupId>
????<artifactId>amqp-client</artifactId>
????<version>5.20.0</version>
??</dependency>
??<!-- 依賴的netty庫(kù) -->
??<dependency>
????<groupId>io.netty</groupId>
????<artifactId>netty-all</artifactId>
????<version>4.1.67.Final</version>
??</dependency>
??<!-- MobileIMSDK的核心庫(kù)(此jar沒有上傳到mave中央庫(kù),請(qǐng)注意本地引用路徑哦) -->
??<dependency>
????<groupId>com.x52im</groupId>
????<artifactId>mobileimsdk-server</artifactId>
????<version>6.5</version>
????<scope>system</scope>
????<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/MobileIMSDKServer.jar</systemPath>
??</dependency>
</dependencies>
②?以RainbowChat的Server工程為例,示例如下圖:

2.3 引用lib包(Eclipse工程)
①?Eclipse中如何引用第3方j(luò)ar包?
跟所有Java工程一樣引用jar包很簡(jiǎn)單,如果沒試過,請(qǐng)查看:Eclipse中導(dǎo)入外部jar包?或?Eclipse下導(dǎo)入外部jar包的3種方式。
②?以MobileIMSDK Server的Demo工程為例,結(jié)果如下圖:

第二部分:編寫代碼
第1步:準(zhǔn)備回調(diào)通知的實(shí)現(xiàn)類
① 框架基本事件回調(diào)實(shí)現(xiàn)類:
public?class?ServerEventListenerImpl?implements?ServerEventListener
{???
????// 用戶身份驗(yàn)證回調(diào)方法定義
????// 服務(wù)端的應(yīng)用層可在本方法中實(shí)現(xiàn)用戶登陸驗(yàn)證。詳細(xì)請(qǐng)參見API文檔說明。
????@Override
????public?int?onUserLoginVerify(String userId, String token, String extra, Channel session)
????{
????????System.out.println("正在調(diào)用回調(diào)方法:OnVerifyUserCallBack...");
????????return?0;
????}
????// 用戶登錄驗(yàn)證成功后的回調(diào)方法定義
????// 服務(wù)端的應(yīng)用層通常可在本方法中實(shí)現(xiàn)用戶上線通知等。詳細(xì)請(qǐng)參見API文檔說明。
????@Override
????public?void?onUserLoginSucess(String userId, String extra, Channel session)
????{
????????System.out.println("正在調(diào)用回調(diào)方法:OnUserLoginAction_CallBack...");
????}
????// 用戶退出登錄回調(diào)方法定義。
????// 服務(wù)端的應(yīng)用層通??稍诒痉椒ㄖ袑?shí)現(xiàn)用戶下線通知等。詳細(xì)請(qǐng)參見API文檔說明。
????@Override
????public?void?onUserLogout(String userId, Object obj, Channel session)
????{
????????System.out.println("正在調(diào)用回調(diào)方法:OnUserLogoutAction_CallBack...");
????}
????// 通用數(shù)據(jù)回調(diào)方法定義(客戶端發(fā)給服務(wù)端的(即接收user_id=0))
????// 上層通??稍诒痉椒ㄖ袑?shí)現(xiàn)如:添加好友請(qǐng)求等業(yè)務(wù)實(shí)現(xiàn)。詳細(xì)請(qǐng)參見API文檔說明。
????@Override
????public?boolean?onTransferMessage4C2S(Protocal p, Channel session)
????{
????????System.out.println("收到了客戶端"+from_user_id+"發(fā)給服務(wù)端的消息:str="+dataContent);
????????return?true;
????}
????// 通道數(shù)據(jù)回調(diào)函數(shù)定義(客戶端發(fā)給客戶端的(即接收user_id>0))。詳細(xì)請(qǐng)參見API文檔說明。
????// 上層通??稍诒痉椒ㄖ袑?shí)現(xiàn)用戶聊天信息的收集,以便后期監(jiān)控分析用戶的行為等^_^。
????@Override
????public?void?onTransferMessage4C2C(Protocal p)
????{
????????System.out.println("收到了客戶端"+from_user_id+"發(fā)給客戶端"+userId+"的消息:str="+dataContent);
????}
????// 通用數(shù)據(jù)實(shí)時(shí)發(fā)送失敗后的回調(diào)函數(shù)定義(客戶端發(fā)給客戶端的(即接收user_id>0))
????// 開發(fā)者可在此方法中處理離線消息的保存等。詳細(xì)請(qǐng)參見API文檔說明。
????@Override
????public?boolean?onTransferMessage_RealTimeSendFaild(Protocal p)
????{
????????System.out.println("客戶端"+from_user_id+"發(fā)給客戶端"+userId+"的消息:str="+dataContent
????????????????????????+"因?qū)崟r(shí)發(fā)送沒有成功,需要上層應(yīng)用作離線處理哦,否則此消息將被丟棄.");
????????return?false;
????}
}
② 服務(wù)端主動(dòng)發(fā)起消息的QoS回調(diào)通知實(shí)現(xiàn)類:
public?class?MessageQoSEventS2CListnerImpl?implements?MessageQoSEventListenerS2C
{???????
????// 消息無法完成實(shí)時(shí)送達(dá)的通知
????@Override
????public?void?messagesLost(ArrayList<;Protocal> lostMessages)
????{
????????System.out.println("【QoS_S2C事件】收到系統(tǒng)的未實(shí)時(shí)送達(dá)事件通知,當(dāng)前共有"
????????????????????????+lostMessages.size()+"個(gè)包QoS保證機(jī)制結(jié)束,判定為【無法實(shí)時(shí)送達(dá)】!");
????}
????// 接收方已成功收到消息的通知
????@Override
????public?void?messagesBeReceived(String theFingerPrint)
????{
????????if(theFingerPrint !=?null)
????????{
????????????System.out.println("【QoS_S2C事件】收到對(duì)方已收到消息事件的通知,fp="+theFingerPrint);
????????}
????}
}
第2步:服務(wù)端最終配置和實(shí)現(xiàn)
public?class?ServerLauncherImpl?extends?ServerLauncher
{
????/**
??????* 靜態(tài)類方法:進(jìn)行一些全局配置設(shè)置。
??????*/
????static
????{
????????// 設(shè)置MobileIMSDK服務(wù)端的UDP網(wǎng)絡(luò)監(jiān)聽端口
????????GatewayUDP.PORT =?7901;
????????// 設(shè)置MobileIMSDK服務(wù)端的TCP網(wǎng)絡(luò)監(jiān)聽端口
????????GatewayTCP.PORT =?8901;
????????// 設(shè)置MobileIMSDK服務(wù)端僅支持UDP協(xié)議
//???????? ServerLauncher.supportedGateways = Gateway.SUPPORT_UDP;
????????// 設(shè)置MobileIMSDK服務(wù)端僅支持TCP協(xié)議
//??????? ServerLauncher.supportedGateways = Gateway.SUPPORT_TCP;
????????// 設(shè)置MobileIMSDK服務(wù)端同時(shí)支持UDP、TCP兩種協(xié)議
????????ServerLauncher.supportedGateways = Gateway.SUPPORT_UDP | Gateway.SUPPORT_TCP;
????????// 開/關(guān)Demog日志的輸出
????????QoS4SendDaemonS2C.getInstance().setDebugable(true);
????????QoS4ReciveDaemonC2S.getInstance().setDebugable(true);
????????ServerLauncher.debug =?true;
????????// 與客戶端協(xié)商一致的心跳頻率模式設(shè)置
//??????? ServerToolKits.setSenseModeUDP(SenseModeUDP.MODE_15S);
//??????? ServerToolKits.setSenseModeTCP(SenseModeTCP.MODE_15S);
????????// 關(guān)閉與Web端的消息互通橋接器(其實(shí)SDK中默認(rèn)就是false)
????????ServerLauncher.bridgeEnabled =?false;
????????// TODO 跨服橋接器MQ的URI(本參數(shù)只在ServerLauncher.bridgeEnabled為true時(shí)有意義)
//??????? BridgeProcessor.IMMQ_URI = "amqp://js:19844713@192.168.0.190";
????????// 設(shè)置最大TCP幀內(nèi)容長(zhǎng)度(不設(shè)置則默認(rèn)最大是 6 * 1024字節(jié))
//??????? GatewayTCP.TCP_FRAME_MAX_BODY_LENGTH = 60 * 1024;
????}
????/**
??????* 實(shí)例構(gòu)造方法。
??????*
??????* @throws IOException
??????*/
????public?ServerLauncherImpl()?throws?IOException
????{
????????super();
????}
????/**
??????* 初始化消息處理事件監(jiān)聽者.
??????????*/
????@Override
????protected?void?initListeners()
????{
????????// ** 設(shè)置各種回調(diào)事件處理實(shí)現(xiàn)類
????????this.setServerEventListener(new?ServerEventListenerImpl());
????????this.setServerMessageQoSEventListener(new?MessageQoSEventS2CListnerImpl());
????}
????public?static?void?main(String[] args)?throws?Exception
????{
????????// 實(shí)例化后記得startup哦,單獨(dú)startup()的目的是讓調(diào)用者可以延遲決定何時(shí)真正啟動(dòng)IM服務(wù)
????????final?ServerLauncherImpl sli =?new?ServerLauncherImpl();
????????// 啟動(dòng)MobileIMSDK服務(wù)端的Demo
????????sli.startup();
????????// 加一個(gè)鉤子,確保在JVM退出時(shí)釋放netty的資源
????????Runtime.getRuntime().addShutdownHook(new?Thread() {
????????????@Override
????????????public?void?run() {
????????????????sli.shutdown();
????????????}
????????});
????}
}
第三部分:常見開發(fā)問題附錄
附錄1:可以讓客戶端更省電嗎?
為了配合Android、iOS客戶端,Server端也需要進(jìn)行設(shè)置。
請(qǐng)調(diào)用以下API進(jìn)行設(shè)置即可(框架默認(rèn)工作在SenseMode.MODE_15S模式下):
// MobileIMSDK核心IM框架的服務(wù)端敏感度模式設(shè)置
ServerLauncherImpl.setSenseMode(SenseMode.MODE_15S);
MobileIMSDK預(yù)定義了多種模式,詳細(xì)API說明:點(diǎn)此進(jìn)入。
特別說明:為了保證算法的一致性,以上設(shè)置需所有平臺(tái)客戶端和服務(wù)端都保持一致,否則將發(fā)生不可預(yù)測(cè)問題。
附錄2:服務(wù)端如何向客戶端推送/發(fā)送數(shù)據(jù)(或消息)?
服務(wù)端使用 LocalSendHelper 類中的sendData系列方法即可,詳見下圖:

API文檔在線地址:http://docs.52im.net/extend/docs/api/mobileimsdk/server_tcp/
附錄3:核心庫(kù)工程與Demo演示工程的關(guān)系說明
如下圖所示:從?Github?或?淘寶?得到的核心庫(kù)工程和Demo演示工程

(▲ 左邊為MobileIMSDK的各平臺(tái)核心庫(kù)工程,右邊為各平臺(tái)的Demo演示工程)
*?什么是核心庫(kù)工程?
核心庫(kù)工程就是MobileIMSDK的所有框架源碼,它只是個(gè)lib庫(kù),它的作用就像Spring boot、Struts、log4j這些第3庫(kù)lib庫(kù)一樣:是打成jar包放到您的工程里使用的,您調(diào)用它就能實(shí)現(xiàn)它提供的功能,它自已本身并不能自已運(yùn)行(你不可能讓log4j或Spring boot能雙擊就運(yùn)行吧?)
*?什么是Demo演示工程?
正如“什么是核心庫(kù)工程?”一節(jié)所說,MobileIMSDK的核心庫(kù)是不能直接運(yùn)行的,它需要打成jar包被您的工程引用并調(diào)用后,才能發(fā)揮它的作用,所以MobileIMSDK的Demo演示工程的目的就是為了告訴你:如何引用MobileIMSDK的核心庫(kù)jar包、如何調(diào)用MobileIMSDK的API,讀Demo代碼就知道如何使用它了(所以Demo代碼唯一的意義就是為您演示庫(kù)的調(diào)用,別無他用)!
*?“我”的工程中使用使用核心庫(kù)工程?
為了方便日后的升級(jí),建議使用MobileIMSDK編譯好的核心庫(kù)jar包,當(dāng)然您也可以直接把MobileIMSDK核心庫(kù)源庫(kù)放到您的工程中(而不是使用編譯好的jar包)。
*?您可以在MobileIMSDK的Github如下目錄中找到打包編譯好的jar包:

附錄4:如何開啟SSL/TLS傳輸加密
1 您需要準(zhǔn)備一個(gè)SSL/TLS證書(支持自簽名證書)
可以使用正規(guī)CA機(jī)構(gòu)簽發(fā)的證書,也可以使用自簽名證書,如何生成自簽名證書可自行百度,這方面資料很豐富。
證書文件就像這樣:

注:如果你不想買證書,也不知道如何生成自簽名證書,可以跟著這篇文章自已做《手把手教你為基于Netty的IM生成自簽名SSL/TLS證書》。
2 代碼中啟用SSL/TLS加密
* 將準(zhǔn)備好的證書放置到服務(wù)端工程的此目錄下(以MobileIMSDK的服務(wù)端Demo工程為例):


* 啟用SSL/TLS配置(取消此行代碼注釋即可):

* 啟用SSL/TLS后的運(yùn)行效果(服務(wù)端控制臺(tái)log中出現(xiàn)此字樣即表示SSL/TLS啟用成功!):

(▲ 服務(wù)端啟動(dòng)時(shí)控制臺(tái)下關(guān)于已開啟TLS/SSL加密的log輸出(run.bat運(yùn)行時(shí)))

(▲ 服務(wù)端啟動(dòng)時(shí)控制臺(tái)下關(guān)于已開啟TLS/SSL加密的log輸出(IDEA中運(yùn)行時(shí)))

(▲ 客戶端發(fā)起WebSocket連接時(shí),服務(wù)端控制臺(tái)下帶有TLS/SSL信息的握手log)
內(nèi)容參考自:http://www.52im.net/thread-63-1-1.html