本文為原創分享,轉載請注明出處。
1、引言
即時通訊IM應用中的聊天消息時間顯示是個再常見不過的需求,現在都講究用戶體驗,所以時間顯示再也不能像傳統軟件一樣簡單粗地暴顯示成“年/月/日 時:分:秒”這樣。所以,市面上幾乎所有的IM都會對聊天消息的時間顯示格化做人性化處理,從而提升用戶體驗(使用感受會明顯友好)。
這兩天正在繼續開發RainbowChat-Web產品,所以正需要這樣的代碼。但經過在即時通訊網的論壇和技術交流群里詢問,以及網上的所謂仿微信例子,都不符合要求。這些例子要么簡陋粗暴(有邏輯bug硬傷)、要么并不完整(可能只是隨手寫的練手代碼,并不適合放到產品中),所以本著做技術精益求精的態度,沒有現成的輪子可用,那就只能造輪子了。
那么,按怎樣的顯示邏輯來實現呢?作為移動端IM的王者,微信無疑處處是標桿,所以本次的消息時間顯示格式,直接參照微信的實現邏輯準沒錯(隨大流雖然沒個性,但不至于非主流)。
* 提示:本文中的代碼實現,是從 RainbowChat 和 RainbowChat-Web 兩個IM產品中扒出來簡化后的結果,是基于完全相同的算法邏輯分別用OC、Java和JavaScript實現的。如您覺得有用,可以改改直接用于您的產品,如您有更好的建議請直接回復和評論。代碼僅供參考,不足之外,還請見諒!
學習交流:
- 即時通訊/推送技術開發交流4群:101279154 [推薦]
- 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM》
(本文同步發布于:http://www.52im.net/thread-2371-1-1.html)
2、相關文章
《用于IM中圖片壓縮的Android工具類源碼,效果可媲美微信 [附件下載]》
《高仿Android版手機QQ可拖拽未讀數小氣泡源碼 [附件下載]》
《Android聊天界面源碼:實現了聊天氣泡、表情圖標(可翻頁) [附件下載]》
《高仿Android版手機QQ首頁側滑菜單源碼 [附件下載]》
《分享java AMR音頻文件合并源碼,全網最全》
《Android版高仿微信聊天界面源碼 [附件下載]》
《高仿手機QQ的Android版鎖屏聊天消息提醒功能 [附件下載]》
《高仿iOS版手機QQ錄音及振幅動畫完整實現 [源碼下載]》
《Android端社交應用中的評論和回復功能實戰分享[圖文+源碼]》
《Android端IM應用中的@人功能實現:仿微博、QQ、微信,零入侵、高可擴展[圖文+源碼]》
3、看看微信中聊天消息的時間顯示規則
先來看看微信中聊天消息的時間顯示成什么樣:
聊天界面(注意聊天界面中默認帶了“時:分”的顯示)
來自微信官方對聊天消息時間顯示的規則說明:
▲ 該規則的定義,主要是2、3條(本圖引用自微信官方FAQ文檔)
4、總結一下微信中聊天消息的時間顯示邏輯
參見第3節中的截圖和微信官方的說明,我們可以總結出微信對于聊天消息時間顯示的規則。
① 微信對于聊天消息時間顯示的規則總結如下(首頁“消息”界面):
1)當聊天消息時間為一周之內時:當天的消息顯示為“小時:分鐘”形式,然后是“昨天”、“前天”,然后就是“星期幾”這個樣子;
2)當聊天消息的時間大于一周時:直接顯示“年/月/日”的時間格式。
② 微信對于聊天消息時間顯示的規則總結如下(聊天內容界面):
1)當聊天消息時間為一周之內時:當天的消息顯示為“小時:分鐘”形式,然后是“昨天 時:分”、“前天 時:分”,然后就是“星期幾 時:分”這個樣子;
2)當聊天消息的時間大于一周時:直接顯示“年/月/日 時:分”的完整時間格式。
注意:聊天內容界面里的時間格式,實際上是首頁“消息”界面里的時間格式加上“時:分”后的結果,所以代碼實現上這兩套代碼是可以重用的,無需兩份代碼。
好了,規則已經摸清,下面將直接上代碼。
5、Android平臺上的代碼實現(標準Java)
5.1 完整源碼
/**
* 返回指定pattern樣的日期時間字符串。
*
* @param dt
* @param pattern
* @return 如果時間轉換成功則返回結果,否則返回空字符串""
* @author 即時通訊網([url=http://www.52im.net]http://www.52im.net[/url])
*/
publicstaticString getTimeString(Date dt, String pattern)
{
try
{
SimpleDateFormat sdf = newSimpleDateFormat(pattern);//"yyyy-MM-dd HH:mm:ss"
sdf.setTimeZone(TimeZone.getDefault());
returnsdf.format(dt);
}
catch(Exception e)
{
return"";
}
}
/**
* 仿照微信中的消息時間顯示邏輯,將時間戳(單位:毫秒)轉換為友好的顯示格式.
* <p>
* 1)7天之內的日期顯示邏輯是:今天、昨天(-1d)、前天(-2d)、星期?(只顯示總計7天之內的星期數,即<=-4d);<br>
* 2)7天之外(即>7天)的邏輯:直接顯示完整日期時間。
*
* @param srcDate 要處理的源日期時間對象
* @param mustIncludeTime true表示輸出的格式里一定會包含“時間:分鐘”,否則不包含(參考微信,不包含時分的情況,用于首頁“消息”中顯示時)
* @return 輸出格式形如:“10:30”、“昨天 12:04”、“前天 20:51”、“星期二”、“2019/2/21 12:09”等形式
* @author 即時通訊網([url=http://www.52im.net]http://www.52im.net[/url])
* @since 4.5
*/
publicstaticString getTimeStringAutoShort2(Date srcDate, booleanmustIncludeTime)
{
String ret = "";
try
{
GregorianCalendar gcCurrent = newGregorianCalendar();
gcCurrent.setTime(newDate());
intcurrentYear = gcCurrent.get(GregorianCalendar.YEAR);
intcurrentMonth = gcCurrent.get(GregorianCalendar.MONTH)+1;
intcurrentDay = gcCurrent.get(GregorianCalendar.DAY_OF_MONTH);
GregorianCalendar gcSrc = newGregorianCalendar();
gcSrc.setTime(srcDate);
intsrcYear = gcSrc.get(GregorianCalendar.YEAR);
intsrcMonth = gcSrc.get(GregorianCalendar.MONTH)+1;
intsrcDay = gcSrc.get(GregorianCalendar.DAY_OF_MONTH);
// 要額外顯示的時間分鐘
String timeExtraStr = (mustIncludeTime?" "+getTimeString(srcDate, "HH:mm"):"");
// 當年
if(currentYear == srcYear)
{
longcurrentTimestamp = gcCurrent.getTimeInMillis();
longsrcTimestamp = gcSrc.getTimeInMillis();
// 相差時間(單位:毫秒)
longdelta = (currentTimestamp - srcTimestamp);
// 當天(月份和日期一致才是)
if(currentMonth == srcMonth && currentDay == srcDay)
{
// 時間相差60秒以內
if(delta < 60* 1000)
ret = "剛剛";
// 否則當天其它時間段的,直接顯示“時:分”的形式
else
ret = getTimeString(srcDate, "HH:mm");
}
// 當年 && 當天之外的時間(即昨天及以前的時間)
else
{
// 昨天(以“現在”的時候為基準-1天)
GregorianCalendar yesterdayDate = newGregorianCalendar();
yesterdayDate.add(GregorianCalendar.DAY_OF_MONTH, -1);
// 前天(以“現在”的時候為基準-2天)
GregorianCalendar beforeYesterdayDate = newGregorianCalendar();
beforeYesterdayDate.add(GregorianCalendar.DAY_OF_MONTH, -2);
// 用目標日期的“月”和“天”跟上方計算出來的“昨天”進行比較,是最為準確的(如果用時間戳差值
// 的形式,是不準確的,比如:現在時刻是2019年02月22日1:00、而srcDate是2019年02月21日23:00,
// 這兩者間只相差2小時,直接用“delta/(3600 * 1000)” > 24小時來判斷是否昨天,就完全是扯蛋的邏輯了)
if(srcMonth == (yesterdayDate.get(GregorianCalendar.MONTH)+1)
&& srcDay == yesterdayDate.get(GregorianCalendar.DAY_OF_MONTH))
{
ret = "昨天"+timeExtraStr;// -1d
}
// “前天”判斷邏輯同上
elseif(srcMonth == (beforeYesterdayDate.get(GregorianCalendar.MONTH)+1)
&& srcDay == beforeYesterdayDate.get(GregorianCalendar.DAY_OF_MONTH))
{
ret = "前天"+timeExtraStr;// -2d
}
else
{
// 跟當前時間相差的小時數
longdeltaHour = (delta/(3600* 1000));
// 如果小于 7*24小時就顯示星期幾
if(deltaHour < 7*24)
{
String[] weekday = {"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
// 取出當前是星期幾
String weedayDesc = weekday[gcSrc.get(GregorianCalendar.DAY_OF_WEEK)-1];
ret = weedayDesc+timeExtraStr;
}
// 否則直接顯示完整日期時間
else
ret = getTimeString(srcDate, "yyyy/M/d")+timeExtraStr;
}
}
}
else
ret = getTimeString(srcDate, "yyyy/M/d")+timeExtraStr;
}
catch(Exception e)
{
System.err.println("【DEBUG-getTimeStringAutoShort】計算出錯:"+e.getMessage()+" 【NO】");
}
returnret;
}
5.2 調用示例
// 用于首頁“消息”界面時
getTimeStringAutoShort2(newDate(), false);
// 用于聊天內容界面時
getTimeStringAutoShort2(newDate(), true);
5.3 運行效果
▲ 上述代碼在RainbowChat Android版上的運行效果(首頁)
▲ 上述代碼在RainbowChat Android版上的運行效果(聊天界面)
6、iOS平臺上的代碼實現(Objective-C)
6.1 完整源碼
源文件TimeTool.h:
#import <Foundation/Foundation.h>
@interfaceTimeTool : NSObject
/**
* 仿照微信中的消息時間顯示邏輯,將時間戳(單位:毫秒)轉換為友好的顯示格式.
* 1)7天之內的日期顯示邏輯是:今天、昨天(-1d)、前天(-2d)、星期?(只顯示總計7天之內的星期數,即<=-4d);
* 2)7天之外(即>7天)的邏輯:直接顯示完整日期時間。
* @param dt 日期時間對象(本次被判斷對象)
* @param includeTime YES表示輸出的格式里一定會包含“時間:分鐘”,否則不包含(參考微信,不包含時分的情況,用于首頁“消息”中顯示時)
* @return 輸出格式形如:“剛剛”、“10:30”、“昨天 12:04”、“前天 20:51”、“星期二”、“2019/2/21 12:09”等形式
* @since 1.3
*/
+ (NSString*)getTimeStringAutoShort2:(NSDate*)dt mustIncludeTime:(BOOL)includeTime;
+ (NSString*)getTimeString:(NSDate*)dt format:(NSString*)fmt;
/**
* 獲得指定NSDate對象iOS時間戳(格式遵從ios的習慣,以秒為單位)。
*/
+ (NSTimeInterval) getIOSTimeStamp:(NSDate*)dat;
/**
* 獲得指定NSDate對象iOS時間戳的long形式(格式遵從ios的習慣,以秒為單位,形如:1485159493)。
*/
+ (long) getIOSTimeStamp_l:(NSDate*)dat;
@end
源文件TimeTool.m:
#import "TimeTool.h"
@implementationTimeTool
// 仿照微信的邏輯,顯示一個人性化的時間字串
+ (NSString*)getTimeStringAutoShort2:(NSDate*)dt mustIncludeTime:(BOOL)includeTime{
NSString*ret = nil;
NSCalendar*calendar = [NSCalendarcurrentCalendar];
// 當前時間
NSDate*currentDate = [NSDatedate];
NSDateComponents*curComponents = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitWeekdayfromDate:currentDate];
NSIntegercurrentYear=[curComponents year];
NSIntegercurrentMonth=[curComponents month];
NSIntegercurrentDay=[curComponents day];
// 目標判斷時間
NSDateComponents*srcComponents = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitWeekdayfromDate:dt];
NSIntegersrcYear=[srcComponents year];
NSIntegersrcMonth=[srcComponents month];
NSIntegersrcDay=[srcComponents day];
// 要額外顯示的時間分鐘
NSString*timeExtraStr = (includeTime?[TimeTool getTimeString:dt format:@" HH:mm"]:@"");
// 當年
if(currentYear == srcYear) {
longcurrentTimestamp = [TimeTool getIOSTimeStamp_l:currentDate];
longsrcTimestamp = [TimeTool getIOSTimeStamp_l:dt];
// 相差時間(單位:秒)
longdelta = currentTimestamp - srcTimestamp;
// 當天(月份和日期一致才是)
if(currentMonth == srcMonth && currentDay == srcDay) {
// 時間相差60秒以內
if(delta < 60)
ret = @"剛剛";
// 否則當天其它時間段的,直接顯示“時:分”的形式
else
ret = [TimeTool getTimeString:dt format:@"HH:mm"];
}
// 當年 && 當天之外的時間(即昨天及以前的時間)
else{
// 昨天(以“現在”的時候為基準-1天)
NSDate*yesterdayDate = [NSDatedate];
yesterdayDate = [NSDatedateWithTimeInterval:-24*60*60 sinceDate:yesterdayDate];
NSDateComponents*yesterdayComponents = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDayfromDate:yesterdayDate];
NSIntegeryesterdayMonth=[yesterdayComponents month];
NSIntegeryesterdayDay=[yesterdayComponents day];
// 前天(以“現在”的時候為基準-2天)
NSDate*beforeYesterdayDate = [NSDatedate];
beforeYesterdayDate = [NSDatedateWithTimeInterval:-48*60*60 sinceDate:beforeYesterdayDate];
NSDateComponents*beforeYesterdayComponents = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDayfromDate:beforeYesterdayDate];
NSIntegerbeforeYesterdayMonth=[beforeYesterdayComponents month];
NSIntegerbeforeYesterdayDay=[beforeYesterdayComponents day];
// 用目標日期的“月”和“天”跟上方計算出來的“昨天”進行比較,是最為準確的(如果用時間戳差值
// 的形式,是不準確的,比如:現在時刻是2019年02月22日1:00、而srcDate是2019年02月21日23:00,
// 這兩者間只相差2小時,直接用“delta/3600” > 24小時來判斷是否昨天,就完全是扯蛋的邏輯了)
if(srcMonth == yesterdayMonth && srcDay == yesterdayDay)
ret = [NSStringstringWithFormat:@"昨天%@", timeExtraStr];// -1d
// “前天”判斷邏輯同上
elseif(srcMonth == beforeYesterdayMonth && srcDay == beforeYesterdayDay)
ret = [NSStringstringWithFormat:@"前天%@", timeExtraStr];// -2d
else{
// 跟當前時間相差的小時數
longdeltaHour = (delta/3600);
// 如果小于或等 7*24小時就顯示星期幾
if(deltaHour <= 7*24){
NSArray<NSString*> *weekdayAry = [NSArrayarrayWithObjects:@"星期日", @"星期一", @"星期二", @"星期三", @"星期四", @"星期五", @"星期六", nil];
// 取出的星期數:1表示星期天,2表示星期一,3表示星期二。。。。 6表示星期五,7表示星期六
NSIntegersrcWeekday=[srcComponents weekday];
// 取出當前是星期幾
NSString*weedayDesc = [weekdayAry objectAtIndex:(srcWeekday-1)];
ret = [NSStringstringWithFormat:@"%@%@", weedayDesc, timeExtraStr];
}
// 否則直接顯示完整日期時間
else
ret = [NSStringstringWithFormat:@"%@%@", [TimeTool getTimeString:dt format:@"yyyy/M/d"], timeExtraStr];
}
}
}
// 往年
else{
ret = [NSStringstringWithFormat:@"%@%@", [TimeTool getTimeString:dt format:@"yyyy/M/d"], timeExtraStr];
}
returnret;
}
+ (NSString*)getTimeString:(NSDate*)dt format:(NSString*)fmt{
NSDateFormatter* format = [[NSDateFormatteralloc] init];
[format setDateFormat:fmt];
return[format stringFromDate:(dt==nil?[TimeTool getIOSDefaultDate]:dt)];
}
+ (NSTimeInterval) getIOSTimeStamp:(NSDate*)dat{
NSTimeIntervala = [dat timeIntervalSince1970];
returna;
}
+ (long) getIOSTimeStamp_l:(NSDate*)dat{
return[[NSNumbernumberWithDouble:[TimeTool getIOSTimeStamp:dat]] longValue];
}
@end
6.2 調用示例
// 用于首頁“消息”界面時
[TimeTool getTimeStringAutoShort2:[NSDatedate] mustIncludeTime:NO];
6.3 運行效果
▲ 上述代碼在RainbowChat iOS版上的運行效果(首頁)
7、Web網頁端的代碼實現(JavaScript)
7.1 完整源碼
抱歉:因文章字數限制,JavaScript版源碼無非法貼上來,請從鏈接:http://www.52im.net/thread-2371-1-1.html,查看JavaScript版完整源碼!
7.2 調用示例
// 用于首頁“消息”界面時
_getTimeStringAutoShort2(1550789954260, false);
// 用于聊天內容界面時
_getTimeStringAutoShort2(1550789954260, true);
7.3 運行效果
▲ 上述代碼在RainbowChat-Web產品上的運行效果
附錄:更多精品資源下載
[1] 精品源碼下載:
《Java NIO基礎視頻教程、MINA視頻教程、Netty快速入門視頻 [有源碼]》
《輕量級即時通訊框架MobileIMSDK的iOS源碼(開源版)[附件下載]》
《開源IM工程“蘑菇街TeamTalk”2015年5月前未刪減版完整代碼 [附件下載]》
《微信本地數據庫破解版(含iOS、Android),僅供學習研究 [附件下載]》
《NIO框架入門(四):Android與MINA2、Netty4的跨平臺UDP雙向通信實戰 [附件下載]》
《NIO框架入門(三):iOS與MINA2、Netty4的跨平臺UDP雙向通信實戰 [附件下載]》
《NIO框架入門(二):服務端基于MINA2的UDP雙向通信Demo演示 [附件下載]》
《NIO框架入門(一):服務端基于Netty4的UDP雙向通信Demo演示 [附件下載]》
《用于IM中圖片壓縮的Android工具類源碼,效果可媲美微信 [附件下載]》
《高仿Android版手機QQ可拖拽未讀數小氣泡源碼 [附件下載]》
《一個WebSocket實時聊天室Demo:基于node.js+socket.io [附件下載]》
《Android聊天界面源碼:實現了聊天氣泡、表情圖標(可翻頁) [附件下載]》
《高仿Android版手機QQ首頁側滑菜單源碼 [附件下載]》
《開源libco庫:單機千萬連接、支撐微信8億用戶的后臺框架基石 [源碼下載]》
《分享java AMR音頻文件合并源碼,全網最全》
《微信團隊原創Android資源混淆工具:AndResGuard [有源碼]》
《一個基于MQTT通信協議的完整Android推送Demo [附件下載]》
《Android版高仿微信聊天界面源碼 [附件下載]》
《高仿手機QQ的Android版鎖屏聊天消息提醒功能 [附件下載]》
《高仿iOS版手機QQ錄音及振幅動畫完整實現 [源碼下載]》
《Android端社交應用中的評論和回復功能實戰分享[圖文+源碼]》
《Android端IM應用中的@人功能實現:仿微博、QQ、微信,零入侵、高可擴展[圖文+源碼]》
《仿微信的IM聊天時間顯示格式(含iOS/Android/Web實現源碼)[圖文+源碼]》
[2] 精品文檔和工具下載:
《計算機網絡通訊協議關系圖(中文珍藏版)[附件下載]》
《史上最全即時通訊軟件簡史(精編大圖版)[附件下載]》
《重磅發布:《阿里巴巴Android開發手冊(規約)》[附件下載]》
《阿里技術結晶:《阿里巴巴Java開發手冊(規約)-終極版》[附件下載]》
《基于RTMP協議的流媒體技術的原理與應用(技術論文)[附件下載]》
《獨家發布《TCP/IP詳解 卷1:協議》CHM版 [附件下載]》
《良心分享:WebRTC 零基礎開發者教程(中文)[附件下載]》
《MQTT協議手冊(中文翻譯版)[附件下載]》
《經典書籍《UNIX網絡編程》最全下載(卷1+卷2、中文版+英文版)[附件下載]》
《音視頻開發理論入門書籍之《視頻技術手冊(第5版)》[附件下載]》
《國際電聯H.264視頻編碼標準官方技術手冊(中文版)[附件下載]》
《Apache MINA2.0 開發指南(中文版)[附件下載]》
《網絡通訊數據抓包和分析工具 Wireshark 使用教程(中文) [附件下載]》
《最新收集NAT穿越(p2p打洞)免費STUN服務器列表 [附件下載]》
《高性能網絡編程經典:《The C10K problem(英文)》[附件下載]》
《即時通訊系統的原理、技術和應用(技術論文)[附件下載]》
《技術論文:微信對網絡影響的技術試驗及分析[附件下載]》
《華為內部3G網絡資料: WCDMA系統原理培訓手冊[附件下載]》
《網絡測試:Android版多路ping命令工具EnterprisePing[附件下載]》
《Android反編譯利器APKDB:沒有美工的日子里繼續堅強的擼》
《一款用于P2P開發的NAT類型檢測工具 [附件下載]》
《兩款增強型Ping工具:持續統計、圖形化展式網絡狀況 [附件下載]》
[3] 精選視頻、演講PPT下載:
《美圖海量用戶的IM架構零基礎演進之路(PPT)[附件下載]》
《開源實時音視頻工程WebRTC的架構詳解與實踐總結(PPT+視頻)[附件下載]》
《QQ空間百億級流量的社交廣告系統架構實踐(視頻+PPT)[附件下載]》
《海量實時消息的視頻直播系統架構演進之路(視頻+PPT)[附件下載]》
《YY直播在移動弱網環境下的深度優化實踐分享(視頻+PPT)[附件下載]》
《QQ空間移動端10億級視頻播放技術優化揭秘(視頻+PPT)[附件下載]》
《RTC實時互聯網2017年度大會精選演講PPT [附件下載]》
《微信分享開源IM網絡層組件庫Mars的技術實現(視頻+PPT)[附件下載]》
《微服務理念在微信海量用戶后臺架構中的實踐(視頻+PPT)[附件下載]》
《移動端IM開發和構建中的技術難點實踐分享(視頻+PPT)[附件下載]》
《網易云信的高品質即時通訊技術實踐之路(視頻+PPT)[附件下載]》
《騰訊音視頻實驗室:直面音視頻質量評估之痛(視頻+PPT)[附件下載]》
《騰訊QQ1.4億在線用戶的技術挑戰和架構演進之路PPT[附件下載]》
《微信朋友圈海量技術之道PPT[附件下載]》
《手機淘寶消息推送系統的架構與實踐(音頻+PPT)[附件下載]》
《如何進行實時音視頻的質量評估與監控(視頻+PPT)[附件下載]》
《Go語言構建高并發消息推送系統實踐PPT(來自360公司)[附件下載]》
《網易IM云千萬級并發消息處理能力的架構設計與實踐PPT [附件下載]》
《手機QQ的海量用戶移動化實踐分享(視頻+PPT)[附件下載]》
《釘釘——基于IM技術的新一代企業OA平臺的技術挑戰(視頻+PPT)[附件下載]》
《微信技術總監談架構:微信之道——大道至簡(PPT講稿)[附件下載]》
《Netty的架構剖析及應用案例介紹(視頻+PPT)[附件下載]》
《聲網架構師談實時音視頻云的實現難點(視頻采訪)》
《滴滴打車架構演變及應用實踐(PPT講稿)[附件下載]》
《微信海量用戶背后的后臺系統存儲架構(視頻+PPT)[附件下載]》
《在線音視頻直播室服務端架構最佳實踐(視頻+PPT)[附件下載]》
《從0到1:萬人在線的實時音視頻直播技術實踐分享(視頻+PPT)[附件下載]》
《微信移動端應對弱網絡情況的探索和實踐PPT[附件下載]》
《Android版微信從300KB到30MB的技術演進(PPT講稿)[附件下載]》
《從零開始搭建瓜子二手車IM系統(PPT)[附件下載]》
《極光分享:高并發海量消息推送系統架構演進(視頻+PPT)[附件下載]》
(本文同步發布于:http://www.52im.net/thread-2371-1-1.html)