前言
- http請求:
每次更新資料都要向對應的埠傳送一次請求,之後返回資料之後關閉連線
- 長連線
客戶端和伺服器一直連著,當有資料更新的時候,伺服器會直接發給客戶端,不需要客戶端主動請求。(client 需要監聽流的輸入)
ps:在這過程中,為了保證服務端和客戶端一直是連線狀態,客戶端會定時不間斷的傳送心跳資料到伺服器,表明還連線著,不然長時間沒有資料更新,會斷開連線,這樣一直有心跳資料的時候,就會保證了連線沒有中斷,至於心跳資料的內容,就是前端後端共同商量的,和請求的資料是單獨的。(通常採用nstimer)
一、tweak 專案整合CocoaAsyncSocket 可採用MonkeyDev 的logos Tweak模版(支援使用CocoaPods)
- pod
platform :ios, `8.0`
inhibit_all_warnings!
#use_frameworks!
target `wlentrust` do
pod `CocoaAsyncSocket`
pod `JSONModel`, `1.1.0`
pod `AFNetworking`, `3.0.4`
pod `XMLDictionary`
end
由於tweak本身就是動態庫,因此暫時只支援靜態庫#use_frameworks!
具體的請看MokeyDev 的logos tweak工程使用注意事項
二、問題解決
- Cannot synthesize weak property in file using manual reference
counting
/Users/devzkn/code/tweak/wlentrust/wlentrust/src/socket/GCDAsyncSocketManager/Manager/GCDAsyncSocketCommunicationManager.m:41:1: Cannot synthesize weak property in file using manual reference counting
- 解決方案:修改專案配置為ARC編譯環境
修改app LLVMXX -language-Object-C 支援ARC
Y-Y-Y-NO
三、程式碼實現
讀訊息的設定
預設讀訊息為timeout 可以設定10
- (void)socketWriteData:(NSString *)data {
// 開始寫資料
NSLog(@"socketWriteData:%@",data);
NSData *requestData = [data dataUsingEncoding:NSUTF8StringEncoding];
[self.socket writeData:requestData withTimeout:-1 tag:0];
// [self socketBeginReadData];// 修改為連線建立之後 就立馬監聽
}
如果想要實時監聽服務端的訊息推送就可以修改,連線一旦建立 就開始讀
- (void)socket:(GCDAsyncSocket *)socket didConnectToHost:(NSString *)host port:(UInt16)port {
[self.socketManager socketBeginReadData];// 修改為連線建立之後 就立馬監聽
}
/**
開始讀資料
*/
#pragma mark - ******** 設定讀資料的timeout 連線建立之後就開始監聽讀取資料
- (void)socketBeginReadData {
NSLog(@"socketBeginReadData");
[self.socket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1 maxLength:0 tag:0];//考慮使用-1
}
業務邏輯的處理
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
// 根據服務端返回的訊息型別,解析引數,處理任務
}
實現實時監聽服務端的流的方法
一旦接受到資料 就開啟下一次的監聽輸入流
receive data -》socketBeginReadData
區分 服務端主動推送 和服務端響應的方式
可以讓服務端新增響應型別 進行區分,或者app 端進行判斷響應資料是否包含reqId,這個reqId 是隻有app 主動發起的請求響應時才會存在
處理服務端的訊息推送
GACRESPONSE_TYPE respType = [json[@"respType"] integerValue];
if(respType == RESPONSE_TYPE_NOTIFY){//訊息通知 服務端的主動通知
//直接傳送通知
// 1、 RESPONSE_TYPE_NOTIFY 處理服務端主動推送的任務
NSMutableDictionary * userInfo = [NSMutableDictionary dictionaryWithObject:json forKey:kRESPONSE_TYPENotificationjsonKey];//respType 傳送json
[[NSNotificationCenter defaultCenter] postNotificationName:kRESPONSE_TYPERESPONSE_TYPE_NOTIFYNotification object:self userInfo:userInfo];
}else{
//2、執行對應的block
SocketDidReadBlock didReadBlock = self.requestsMap[requestID];
// if (errorCode != 0) {
//
// jsonError = [[NSError alloc]initWithDomain:NSURLErrorDomain code:errorCode userInfo:nil];
// }
if (didReadBlock) {
didReadBlock(jsonError, json);
}
}
[self.socketManager socketBeginReadData];// 修改為連線建立之後 就立馬監聽
異常斷開連線處理
#pragma mark - ******** 失敗重新連線
- (void)socketDidDisconnect:(GCDAsyncSocket *)socket withError:(NSError *)err {
- (void)socketWriteDataWithRequestType:(GACRequestType)type
requestBody:(nonnull NSDictionary *)body
completion:(nullable SocketDidReadBlock)callback {
NSLog(@"socketWriteData:%@",body);
if (self.socketManager.connectStatus == -1) {
NSLog(@"socket 未連通");
- (void)socket:(GCDAsyncSocket *)socket didConnectToHost:(NSString *)host port:(UInt16)port {
self.socketManager.connectStatus = 1;//此處的狀態設定,提前到建立連線的地方
//此時將重連的時鐘刪除
[self.socketManager invalidatereconnectTimer];
服務端的搭建可以採用Node.js
待續
工程師必備技能 – 90分鐘自己開發一個chrome擴充套件