Socket-長連線(心跳包)的實現
#import "GCDSocketManager.h"
// 但是我用的自己電腦做測試,所以用的這個IP地址
#define SocketHost @"127.0.0.1"
// 埠是隨意寫的
#define SocketPort 9999
@interface GCDSocketManager()<GCDAsyncSocketDelegate>
//握手次數
@property(nonatomic,assign)NSInteger pushCount;
//斷開重連定時器
@property(nonatomic,strong)NSTimer *timer;
// 檢測心跳的定時器
@property (nonatomic,strong)NSTimer *heartBeatTimer;
//重連次數
@property(nonatomic,assign)NSInteger reconnectCount;
@end
@implementation GCDSocketManager
//全域性訪問點
+ (instancetype)sharedSocketManager {
staticGCDSocketManager *_instance =nil;
staticdispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[selfalloc] init];
});
return _instance;
}
//可以在這裡做一些初始化操作
- (instancetype)init
{
self = [superinit];
if (self) {
}
returnself;
}
#pragma mark - 這裡是操作傳送心跳包定時器的方法
- (void)openTimer {
[selfcloseTimer];
if (self.heartBeatTimer ==nil || !self.heartBeatTimer
self.heartBeatTimer = [NSTimerscheduledTimerWithTimeInterval:5target:selfselector:@selector(heartCheck)userInfo:nilrepeats:YES];
}
}
- (void)closeTimer {
[self.heartBeatTimerinvalidate];
self.heartBeatTimer =nil;
}
- (void)heartCheck {
[selfsendDataToServer];
}
#pragma mark 請求連線
//連線
- (void)connectToServer {
self.pushCount =0;
self.socket = [[GCDAsyncSocketalloc] initWithDelegate:selfdelegateQueue:dispatch_get_main_queue()];
NSError *error =nil;
[self.socketconnectToHost:SocketHostonPort:SocketPorterror:&error];
if (error) {
NSLog(@"SocketConnectError:%@",error);
}
}
#pragma mark 連線成功
//連線成功的回撥
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
NSLog(@"socket連線成功");
[selfopenTimer];
}
//連線成功後向伺服器傳送資料
- (void)sendDataToServer {
//傳送資料程式碼省略...
NSString *str =@"你好服務端,我是帥氣的客戶端,Kean..";
NSData *jsonData = [strdataUsingEncoding:NSUTF8StringEncoding];
//傳送
[self.socketwriteData:jsonData withTimeout:-1tag:1];
//讀取資料
[self.socketreadDataWithTimeout:-1tag:200];
}
//連線成功向伺服器傳送資料後,伺服器會有響應
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
NSString *str = [[NSStringalloc] initWithData:dataencoding:NSUTF8StringEncoding];
NSLog(@"客戶端收到資料---%@",str);
[self.socketreadDataWithTimeout:-1tag:200];
//伺服器推送次數
self.pushCount++;
//在這裡進行校驗操作,情況分為成功和失敗兩種,成功的操作一般都是拉取資料
}
#pragma mark 連線失敗
//連線失敗的回撥
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err {
NSLog(@"Socket連線失敗");
[selfcloseTimer];
self.pushCount =0;
NSUserDefaults *userDefaults = [NSUserDefaultsstandardUserDefaults];
NSString *currentStatu = [userDefaultsvalueForKey:@"Statu"];
//程式在前臺才進行重連
if ([currentStatuisEqualToString:@"foreground"]) {
//重連次數
self.reconnectCount++;
//如果連線失敗累加1秒重新連線減少伺服器壓力
NSTimer *timer = [NSTimerscheduledTimerWithTimeInterval:1.0 *self.reconnectCounttarget:selfselector:@selector(reconnectServer)userInfo:nilrepeats:NO];
self.timer = timer;
}
}
//如果連線失敗,5秒後重新連線
- (void)reconnectServer {
self.pushCount =0;
self.reconnectCount =0;
//連線失敗重新連線
NSError *error =nil;
[self.socketconnectToHost:SocketHostonPort:SocketPorterror:&error];
if (error) {
NSLog(@"SocektConnectError:%@",error);
}
}
#pragma mark 斷開連線
//切斷連線
- (void)cutOffSocket {
NSLog(@"socket斷開連線");
self.pushCount =0;
self.reconnectCount =0;
[self.timerinvalidate];
self.timer =nil;
[self.socketdisconnect];
}
@end
THIRD.配置完成,以下是後臺的log