iOS AsyncSocket封装、长连接

//

//  VVETCPSocket.h

//  SmallP

//

//  Created by mifit on 15/7/3.

//  Copyright (c) 2015 mi. All rights reserved.

//


#import <Foundation/Foundation.h>

/*  Point to Point connected

 *

 */


typedef void(^connectedToHostBlock) (NSString *hostIP,NSInteger port);

typedef void(^sendCompletedBlock)(NSInteger tag,NSString *error);

typedef void(^didDisconnectedBlock)();


typedef void(^newConnectedBlock)();

typedef void(^readDataBlock)(NSData *data,NSInteger tag);


typedef NS_ENUM(NSInteger, VVEConnectState) {

    VVEConnectStateDisConnected = 0,

    VVEConnectStateConnected,

    VVEConnectStateConnecting

};

/*

 *  一对一读写socket

 */

@interface VVETCPSocket : NSObject

@property (nonatomic,readonly)VVEConnectState connectState;

@property (nonatomic,assign)BOOL isScanConnect;//是否在扫描连接

@property (nonatomic,strong)NSString *ip;//remote ip

@property (nonatomic,strong)NSString *name;//remote device name

@property (nonatomic,assign)BOOL isWifi;//是否是wifi,否则热点

/// 单例

+ (VVETCPSocket *)shareInstance;

/// 发送部分

/// 链接到指定ipport的设备,链接成功调用block

- (void)connectToHost:(NSString *)hostIP port:(NSInteger)port connected:(connectedToHostBlock)block didDisconnected:(didDisconnectedBlock)disBlock;

/// 连接成功后发送数据,发送完毕调用block

- (void)sendData:(NSString *)dataStr tag:(NSInteger)tag finishWritedBlock:(sendCompletedBlock)block;

- (void)disconnected;


/// 读取数据,默认超时6s

- (void)readData:(readDataBlock)block;

/// 读取数据

- (void)readData:(readDataBlock)block timeout:(NSInteger)timeout;

/// 接收部分

- (void)acceptPort:(NSInteger)port newConnect:(newConnectedBlock)nBlock readTag:(NSUInteger)tag didReadData:(readDataBlock)rBlock;

@end



//

//  VVETCPSocket.m

//  SmallP

//

//  Created by mifit on 15/7/3.

//  Copyright (c) 2015 mi. All rights reserved.

//


#import "VVETCPSocket.h"

#import "AsyncSocket.h"



#define HostPort 9900


/// 心跳间隔

const NSInteger bitInterval =20;

/// 断开连接后尝试自动连接上一次连接的ip 3次。

const NSInteger tryTimeMax =3;


@interface VVETCPSocket()

@property (nonatomic,strong)AsyncSocket *serverSocket;

@property (nonatomic,strong)AsyncSocket *receiveSocket;

@property (nonatomic,strong)AsyncSocket *sendSocket;


@property (nonatomic,copy)connectedToHostBlock connectedBlock;

@property (nonatomic,copy)didDisconnectedBlock disConnectedBlock;


@property (nonatomic,copy)newConnectedBlock newConnectedBlock;

@property (nonatomic,copy)sendCompletedBlock completedSendBlock;

@property (nonatomic,copy)readDataBlock readBlock;


/// tag 读取tag

@property (nonatomic,assign)NSInteger readTag;

/// 心跳count

@property (nonatomic,assign)NSInteger heartbitCount;

/// gcd

@property (nonatomic,strong)dispatch_source_t sourceTimer;

/// 当前剩余尝试连接次数,设置0以下可以不尝试重连

@property (nonatomic,assign)NSInteger tryTimeCurrent;

@end


@implementation VVETCPSocket

+ (VVETCPSocket *)shareInstance{


    static VVETCPSocket *tcpSocket =nil;

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        tcpSocket = [[VVETCPSocket alloc]init];

    });

    return tcpSocket;

}


- (AsyncSocket *)receiveSocket{

    if (!_receiveSocket){

        _receiveSocket = [[AsyncSocketalloc]initWithDelegate:self];

        [_receiveSocketsetRunLoopModes:[NSArrayarrayWithObject:NSRunLoopCommonModes]];

    }

    return_receiveSocket;

}


- (AsyncSocket *)sendSocket{

    if (!_sendSocket) {

        _sendSocket = [[AsyncSocketalloc]initWithDelegate:self];

         [_sendSocketsetRunLoopModes:[NSArrayarrayWithObject:NSRunLoopCommonModes]];

    }

    return_sendSocket;

}


- (void)keepHeartBit{

    _heartbitCount =bitInterval; //倒计时时间

    if (self.sourceTimer ==nil) {

        dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

        dispatch_source_t timer =dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0, 0,queue);

        self.sourceTimer = timer;

        dispatch_source_set_timer(timer,dispatch_walltime(NULL,0),2.0*NSEC_PER_SEC,0); //每秒执行

        dispatch_source_set_event_handler(timer, ^{

            if(_heartbitCount <=0){ //倒计时结束,关闭

                //dispatch_source_cancel(timer);

                _heartbitCount =bitInterval;

                dispatch_async(dispatch_get_main_queue(), ^{

                    NSLog(@"send heart bit");

                    [self sendData:@"" tag:100 finishWritedBlock:^(NSInteger tag,NSString *error) {

                        NSLog(@"send end");

                        if (error) {

                            NSLog(@"heart bit error:%@",error);

                        }

                    }];

                    

                    [self readData:^(NSData *data, NSInteger tag){

                        NSLog(@"heat bit response.");

                    }];

                });

                

                

            }else{

                _heartbitCount-=2;

                NSLog(@"-");

            }

        });

        dispatch_resume(timer);

    }

}

#pragma mark - public method

- (void)connectToHost:(NSString *)hostIP port:(NSInteger)port connected:(connectedToHostBlock)block didDisconnected:(didDisconnectedBlock)disBlock;{

    if (self.connectState ==VVEConnectStateConnected) {

        self.tryTimeCurrent =0;

        [self.sendSocketdisconnect];

    }

    if (self.connectState !=VVEConnectStateConnecting && ![self.sendSocketisConnected]) {

        self.ip = hostIP;

        NSError *error;

        self.connectedBlock = block;

        self.disConnectedBlock = disBlock;

        NSLog(@"try to connect to ip:%@",hostIP);

        [self.sendSocketconnectToHost:hostIP onPort:portwithTimeout:10error:&error];

        _connectState =VVEConnectStateConnecting;

    }

}


- (void)sendData:(NSString *)dataStr tag:(NSInteger)tag finishWritedBlock:(sendCompletedBlock)block{

    self.completedSendBlock = block;

    if (self.connectState ==VVEConnectStateConnected) {

        [self keepHeartBit];

        NSString *strSend = [NSStringstringWithFormat:@"%@\n",dataStr];

        NSData *data = [strSenddataUsingEncoding:NSUTF8StringEncoding];

        [self.sendSocketwriteData:data withTimeout:-1tag:tag];

    }else{

        if (self.completedSendBlock) {

            self.completedSendBlock(tag,NSLocalizedString(@"Disconnect",nil));

        }

    }

}


- (void)readData:(readDataBlock)block{

    [self.sendSocketreadDataWithTimeout:10tag:self.readTag];

    self.readBlock = block;

}


- (void)readData:(readDataBlock)block timeout:(NSInteger)timeout{

    [self.sendSocketreadDataWithTimeout:timeout tag:self.readTag];

    self.readBlock = block;

}


- (void)disconnected{

    if (self.sourceTimer) {

        dispatch_source_cancel(self.sourceTimer);

        self.sourceTimer =nil;

    }

    if (self.connectState ==VVEConnectStateConnected) {

        self.tryTimeCurrent =0;

        [self.sendSocketdisconnect];

    }

}


- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err{

    NSLog(@"disconnect:%@",err);

}


- (void)acceptPort:(NSInteger)port newConnect:(newConnectedBlock)nBlock readTag:(NSUInteger)tag didReadData:(readDataBlock)rBlock{

    NSError *error;

    [self.receiveSocketdisconnect];

    [self.receiveSocketacceptOnPort:port error:&error];

    self.newConnectedBlock = nBlock;

    self.readBlock = rBlock;

    self.readTag = tag;

}


#pragma mark - AsyncSocket delegate

- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{

    _connectState =VVEConnectStateConnected;

    NSLog(@"==connected==%@",host);

    [selfkeepHeartBit];

    if (self.connectedBlock) {

        self.connectedBlock(host,port);

    }

    self.tryTimeCurrent =tryTimeMax;

}


- (void)onSocketDidDisconnect:(AsyncSocket *)sock{

    NSLog(@"==disconnected==");

    if (self.sourceTimer) {

        dispatch_source_cancel(self.sourceTimer);

        self.sourceTimer =nil;

    }

    

    _connectState =VVEConnectStateDisConnected;

    if (self.disConnectedBlock) {

        self.disConnectedBlock();

    }

    

    if (self.tryTimeCurrent >0 && !self.isScanConnect) {

        NSError *error;

        [self.sendSocketconnectToHost:self.iponPort:HostPortwithTimeout:10error:&error];

        _connectState =VVEConnectStateConnecting;

        self.tryTimeCurrent--;

    }

}


- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag{

    if (self.completedSendBlock) {

        self.completedSendBlock(tag,nil);

    }

}


- (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket{

    if (self.receiveSocket != newSocket) {

        self.receiveSocket = newSocket;

        [self.receiveSocketreadDataWithTimeout:-1tag:self.readTag];

        if (self.newConnectedBlock) {

            self.newConnectedBlock();

        }

    }

}


- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{

//    NSString *st = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];

//    NSLog(@"recv:%@+",st);

    [self.receiveSocketreadDataWithTimeout:-1tag:self.readTag];

    if (self.readBlock) {

        self.readBlock(data,tag);

    }

}

@end



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值