1. 程式人生 > >Socket-長連線(心跳包)的實現

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