您的位置:首页 > 移动开发 > IOS开发

iOS长连接Socket使用--AsyncSocket

2016-07-21 17:13 519 查看
 SOCKET:TCP/IP网络的API。Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。Socket的出现只是使得程序员更方便地使用TCP/IP协议栈而已,是对TCP/IP协议的抽象,从而形成了我们知道的一些最基本的函数接口。

一般有不定时的向服务器传送数据的需求时,使用长连接, iOS开发中长连接的使用一般使用第三方库AsyncSocket, 对socket的封装比较好,使用起来很方便.

下载AsyncSocket    https://github.com/robbiehanson/CocoaAsyncSocket 
将RunLoop文件夹下的AsyncSocket.h, AsyncSocket.m, AsyncUdpSocket.h, AsyncUdpSocket.m 文件拷贝到自己的project中

添加 依赖库  CFNetwork.framework

1. 先创建一个单例类,命名SocketTool

SocketTool.h

//
//  SocketTool.h
//  SocketTest

#import <Foundation/Foundation.h>

@interface SocketTool : NSObject

+ (SocketTool *)shareInstance;

@end


SocketTool.m

#import "SocketTool.h"

@implementation SocketTool

+ (SocketTool *)shareInstance {

static SocketTool *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}

@end


2. 在SocketTool.h中导入

#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
#import <unistd.h>
#import "AsyncSocket.h"


声明变量

@property (nonatomic, strong) AsyncSocket *socket;
@property (nonatomic, copy) NSString *socketHost;
@property (nonatomic, assign) UInt16 socketPort; //端口号
@property (nonatomic, strong) NSTimer *connectTimer; // 计时器


声明连接和断开的方法

- (void)socketConnectHost; // socket连接

// 声明断开连接方法
- (void)cutOffSocket; // 断开socket连接.


代理

@interface SocketTool : NSObject<AsyncSocketDelegate>


枚举

enum {
SocketOfflineByServer, // 服务器掉线, 默认为0.
SocketOfflineByUser, //用户主动cut.
};


在SocketTool.m实现方法

//连接.
- (void)socketConnectHost {

self.socket  = [[AsyncSocket alloc] initWithDelegate:self];
NSError *error = nil;
[self.socket connectToHost:self.socketHost onPort:self.socketPort withTimeout:30 error:&error];
}

//切断socket
- (void)cutOffSocket {

self.socket.userData = SocketOfflineByUser; // 声明是由用户主动切断.
[self.connectTimer invalidate];
self.connectTimer = nil;
[self.socket disconnect];
}


在SocketTool.m成功 和 失败的回调方法

#pragma mark ----------------------- 连接成功回调 --------------------------
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port {
NSLog(@"连接成功");
// 每隔30秒向服务器发送心跳包  一般设置30秒发送一次心跳包
self.connectTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(longConnectToSocket) userInfo:nil repeats:YES];
[self.connectTimer fire];
}

//--------------------------------- will连接失败回调 -------------------------------
- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err {
NSLog(@"连接失败");
}

//---------------------------------  连接失败回调 -------------------------------
// 重连
- (void)onSocketDidDisconnect:(AsyncSocket *)sock {
NSLog(@"sorry the connect is failure %ld", sock.userData);
if (sock.userData == SocketOfflineByServer) {
//服务器掉线, 重连
NSLog(@"服务器掉线**********请重新连接");
[self socketConnectHost];
} else if (sock.userData == SocketOfflineByUser) {
// 如果用户断开, 不进行重连.
return;
}
}


得到服务器下发消息会调用的方法

// 如果得到数据, 就会调用回调方法.
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
NSLog(@"长连接下发的消息*****************%@",data);
// 对得到的data值进行解析与转换即可.

}


心跳连接方法

// 心跳连接
- (void)longConnectToSocket {
// 根据服务器要求发送固定格式的数据, 假设为指令@"longConnect", 但是一般不会是这么简单地指令.
NSLog(@"我发送了一次心跳包");
NSString *longConnect = @"longConnect";
NSData *dataStream = [longConnect dataUsingEncoding:NSUTF8StringEncoding];

[self.socket writeData:dataStream withTimeout:1 tag:1];

}


至此连接类已经完成

使用

导入#import "SocketTool.h"

[SocketTool shareInstance].socketHost = @"<code class="hljs actionscript"><span class="hljs-string"><span class="hljs-string">192.186.100.21</span></span></code>";// host设定
[SocketTool shareInstance].socketPort = 8282;// port设定

// 在连接前先进行手动断开
[SocketTool shareInstance].socket.userData = SocketOfflineByUser;
[[SocketTool shareInstance] cutOffSocket];

// 确保断开后再连,如果对一个正处于连接状态的socket进行连接,会出现崩溃
[SocketTool shareInstance].socket.userData = SocketOfflineByServer;
[[SocketTool shareInstance] socketConnectHost];
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息