概述
//
// 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;
/// 发送部分
/// 链接到指定ip和port的设备,链接成功调用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
最后
以上就是爱撒娇铃铛为你收集整理的iOS AsyncSocket封装、长连接的全部内容,希望文章能够帮你解决iOS AsyncSocket封装、长连接所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复