轉(zhuǎn)載地址http://mogu.io/mat-tt-network-01-23](http://mogu.io/mat-tt-network-01-23)
mac TeamTalk驻债,底層通信维费,主要在這里!
概述
為了增加程序的可擴(kuò)展性,以及降低后期維護(hù)的成本恨闪,在MAC TT的開發(fā)后期,我決定重構(gòu)TT的網(wǎng)絡(luò)層。
重構(gòu)之后的網(wǎng)絡(luò)層實(shí)例化了網(wǎng)絡(luò)請求,這樣有一個好處就是方便維護(hù)網(wǎng)絡(luò)請求的生命周期气笙。每一個網(wǎng)絡(luò)請求都把自己的數(shù)據(jù)打包和解包封裝起來。換一種說法就是每個網(wǎng)絡(luò)請求都是相互獨(dú)立的怯晕。相對于之前把數(shù)據(jù)打包放在一個PackManager中潜圃,把解包的操作分發(fā)到UserModule和MessageModule等module中的做法更加解耦,后期想添加一種新的網(wǎng)絡(luò)請求時可以做到對原先的代碼原封不動舟茶,
新的網(wǎng)絡(luò)層通過block將發(fā)包和收包綁到了一塊兒谭期。這樣一來開發(fā)者在函數(shù)的生命周期中就可以對收到的包做相應(yīng)的處理,而不需要用通知在程序的某個陰暗角落做不為人知的處理吧凉。因?yàn)樵谡麄€程序中我們有很多中的網(wǎng)絡(luò)請求隧出,如果用通知的話,我們至少要添加相同種類的通知客燕,在很大程度上增加了程序的復(fù)雜度以及維護(hù)成本鸳劳,完成這一優(yōu)化更多的是依靠block的特性。
新的網(wǎng)絡(luò)層框架保證了數(shù)據(jù)包的一致性也搓,協(xié)議頭中有seqNo赏廓,用于保證數(shù)據(jù)包的一致性。原先的網(wǎng)絡(luò)層只管發(fā)送數(shù)據(jù)包傍妒,缺少了對返回數(shù)據(jù)包協(xié)議頭的校驗(yàn)幔摸。假設(shè)這樣一個場景A發(fā)送了兩個獲取用戶信息的數(shù)據(jù)包a1和a2,這時服務(wù)器端會返回兩個數(shù)據(jù)包b1和b2颤练。原先的網(wǎng)絡(luò)層這時是沒法知道哪個數(shù)據(jù)包對應(yīng)的是哪個數(shù)據(jù)包的既忆。新的網(wǎng)絡(luò)層協(xié)議將seqNo作為請求生命周期維護(hù)的標(biāo)識符組成部分,在收到數(shù)據(jù)包的時候?qū)?shù)據(jù)包協(xié)議頭解析嗦玖,根據(jù)協(xié)議頭中的seqNo以及其他部分找到維護(hù)列表中的相應(yīng)的請求患雇,這樣就做到了一一對應(yīng)。
新的網(wǎng)絡(luò)層分為協(xié)議宇挫、SuperAPI苛吱、APISchedule
三部分組成,接下來將逐篇展開
協(xié)議 - APIScheduleProtocol
APIScheduleProtocol定義了每個網(wǎng)絡(luò)請求中不同的部分以及每個網(wǎng)絡(luò)請求需要實(shí)現(xiàn)的接口器瘪。APIScheduleProtocol協(xié)議是作為一個可擴(kuò)展性的基石翠储,后續(xù)的所有網(wǎng)絡(luò)請求類都需要實(shí)現(xiàn)這個協(xié)議。APIScheduleProtocol
協(xié)議定義了以下幾個接口:
-(int)requestTimeOutTimeInterval; 返回請求超時時間
-(int)requestServiceID; 返回請求的ServiceID橡疼,用于請求生命周期的維護(hù)
-(int)responseServiceID; 返回返回數(shù)據(jù)包的ServiceID援所,用于請求的維護(hù)校驗(yàn)
-(int)requestCommendID; 返回請求的CommandID,用于請求生命周期的維護(hù)
-(int)responseCommendID; 返回返回數(shù)據(jù)包的CommandID欣除,用于請求的維護(hù)校驗(yàn)
-(Analysis)analysisReturnData; 返回數(shù)據(jù)解包的block住拭,在收到數(shù)據(jù)并通過協(xié)議頭的解析找到相應(yīng)的請求實(shí)體的時候,就會調(diào)用這個block,Analysis的定義如下:
typedef id(^Analysis)(NSData* data);
-(Package)packageRequestObject;返回數(shù)據(jù)打包的block滔岳,在發(fā)送請求之前調(diào)用這個block去對相應(yīng)的數(shù)據(jù)打包成符合服務(wù)器端協(xié)議的數(shù)據(jù)包瘟檩。Package的定義如下:
typedef NSMutableData*(^Package)(id object,uint16_t seqNO);
創(chuàng)建新類型的請求的時候,只要實(shí)現(xiàn)這個協(xié)議中的接口就可以了澈蟆,開發(fā)者完全不用關(guān)系是怎么發(fā)送怎么維護(hù)的。如果你認(rèn)真看了卓研,或者我說的夠明白趴俘,這里你也許會問,我實(shí)現(xiàn)了這個協(xié)議之后我怎么去發(fā)起請求呢奏赘,我怎么去維護(hù)呢寥闪?我們馬上來講SuperAPI!Dヌ省疲憋!
SuperAPI
一個請求實(shí)體在實(shí)現(xiàn)了APIScheduleProtocol協(xié)議之后已經(jīng)完成了絕大部分他應(yīng)該做的東西了,但還差最關(guān)鍵的一步:發(fā)送請求的接口
梁只。在這個接口中我們需要完成請求的維護(hù)注冊缚柳、數(shù)據(jù)打包、發(fā)送搪锣,這個每個請求都需要的操作秋忙。所以就有了SuperAPI。SuperAPI定義了發(fā)送請求的唯一接口构舟。
- (void)requestWithObject:(id)object Completion:(RequestCompletion)completion;
所有的請求都需要調(diào)用這個接口去和服務(wù)器端交互灰追,在某種程度上來說也降低了程序的復(fù)雜度。接口中有兩個參數(shù):
object : 這是請求時帶的除去協(xié)議頭中數(shù)據(jù)之外的數(shù)據(jù)(協(xié)議頭中的數(shù)據(jù)在APIScheduleProtocol中已經(jīng)定義好了接口)狗超。比如你要獲取某個用戶的信息弹澎,這時候object就是用戶的ID。
completion : 這是在客戶端收到數(shù)據(jù)并解析后確認(rèn)分發(fā)給自己努咐,自己解析完之后調(diào)用的block(這些邏輯操作都是定義在APISchedule中的)苦蒿。RequestCompletion 定義如下:
typedef void(^RequestCompletion)(id response,NSError* error);
假如 error為nil,則說明是請求成功反之則是失敗麦撵。completion block 使用戶在調(diào)用此接口的函數(shù)中可以對返回的數(shù)據(jù)做相應(yīng)的處理刽肠。避免了大量使用通知的情況。簡化了開發(fā)者的程序邏輯和復(fù)雜度免胃。
這個接口不需要子類去重載音五,因?yàn)樗械慕涌诎l(fā)送請求的邏輯都是一樣的。以下是接口實(shí)現(xiàn):
- (void)requestWithObject:(id)object Completion:(RequestCompletion)completion
{
//seqNo
theSeqNo ++;
_seqNo = theSeqNo;
//注冊接口
BOOL registerAPI = [[DDAPISchedule instance] registerApi:(id<DDAPIScheduleProtocol>)self];
if (!registerAPI)
{
return;
}
//注冊請求超時
if ([(id<DDAPIScheduleProtocol>)self requestTimeOutTimeInterval] > 0)
{
[[DDAPISchedule instance] registerTimeoutApi:(id<DDAPIScheduleProtocol>)self];
}
//保存完成塊
self.completion = completion;
//數(shù)據(jù)打包
Package package = [(id<DDAPIScheduleProtocol>)self packageRequestObject];
NSMutableData* requestData = package(object,_seqNo);
//發(fā)送
if (requestData)
{
[[DDAPISchedule instance] sendData:requestData];
}
}
代碼不多主要的請求生命周期的維護(hù)是在APISchedule中去實(shí)現(xiàn)的羔沙。(這個接口的實(shí)現(xiàn)主要是借助設(shè)計模式中的模板模式
)躺涝。
APISchedule
今天先到這里,APISchedule 部分會在Mac TeamTalk 網(wǎng)絡(luò)層(2)出現(xiàn);預(yù)告在Mac TeamTalk 網(wǎng)絡(luò)層(3)中還會出現(xiàn)對于這一框架的擴(kuò)展哦坚嗜!