一、简介
CocoaAsyncSocket是谷歌的开发者,基于BSD-Socket写的一个IM框架,可在github下载 ,它给Mac和iOS提供了易于使用的、强大的异步套接字库,向上封装出简单易用OC接口。省去了我们面向Socket以及数据流Stream等繁琐复杂的编程。其结构框架简介示意图如下:
整个库就这么两个类,一个基于TCP,一个基于UDP。其中基于TCP的GCDAsyncSocket,大概8000多行代码。而GCDAsyncUdpSocket稍微少一点,也有5000多行。
1.GCDAsyncSocket.
用GCD搭建的基于TCP/IP协议的socket网络库
GCDAsyncSocket is a TCP/IP socket networking library built atop Grand Central Dispatch. -- 来源于CocoaAsyncSocket.
2.GCDAsyncUdpSocket
用GCD搭建的基于UDP/IP协议的socket网络库.
GCDAsyncUdpSocket is a UDP/IP socket networking library built atop Grand Central Dispatch..--来源于CocoaAsyncSocket.
二、客户端
因为,大部分项目已经有服务端socket,所以,先讲解客户端创建过程.
步骤:
1.继承GCDAsyncSocketDelegate协议.
2.声明属性
// 客户端socket
@property (strong, nonatomic) GCDAsyncSocket *clientSocket;
3.创建socket并指定代理对象为self,代理队列必须为主队列.
self.clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
4.连接指定主机的对应端口.
NSError *error = nil;
self.connected = [self.clientSocket connectToHost:self.addressTF.text onPort:[self.portTF.text integerValue] viaInterface:nil withTimeout:-1 error:&error];
5.成功连接主机对应端口号.
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
// NSLog(@"连接主机对应端口%@", sock);
[self showMessageWithStr:@"链接成功"];
[self showMessageWithStr:[NSString stringWithFormat:@"服务器IP: %@-------端口: %d", host,port]];
// 连接成功开启定时器
[self addTimer];
// 连接后,可读取服务端的数据
[self.clientSocket readDataWithTimeout:- 1 tag:0];
self.connected = YES;
}
IP---其中的IP服务器的IP地址
6、向服务器发送数据
向服务器发送数据主要通过- (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag 来向后台发送数据的
- (IBAction)sendMessageAction:(id)sender
{
NSData *data = [self.messageTextF.text dataUsingEncoding:NSUTF8StringEncoding];
// withTimeout 0 : 等待时间
// tag : 消息标记
[self.clientSocket writeData:data withTimeout:0 tag:0];
}
7、读取数据
/**
读取数据
@param sock 客户端socket
@param data 读取到的数据
@param tag 本次读取的标记
*/
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
NSString *text = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
[self showMessageWithStr:text];
// 读取到服务端数据值后,能再次读取
[self.clientSocket readDataWithTimeout:- 1 tag:0];
}
主要通过方法-(void) readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag来进行的
8、断开连接
/**
客户端socket断开
@param sock 客户端socket
@param err 错误描述
*/
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
[self showMessageWithStr:@"断开连接"];
self.clientSocket.delegate = nil;
self.clientSocket = nil;
self.connected = NO;
[self.connectTimer invalidate];
}
9、建立心跳
心跳连接中发送给服务端的数据只是作为测试代码,根据你们公司需求,或者和后台商定好心跳包的数据以及发送心跳的时间间隔.客户端发送心跳包,服务端也需要有对应的心跳检测,以此检测客户端是否在线.
// 计时器
@property (nonatomic, strong) NSTimer *connectTimer;
// 添加定时器
- (void)addTimer
{
// 长连接定时器
self.connectTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(longConnectToSocket) userInfo:nil repeats:YES];
// 把定时器添加到当前运行循环,并且调为通用模式
[[NSRunLoop currentRunLoop] addTimer:self.connectTimer forMode:NSRunLoopCommonModes];
}
// 心跳连接
- (void)longConnectToSocket
{
// 发送固定格式的数据,指令@"longConnect"
float version = [[UIDevice currentDevice] systemVersion].floatValue;
NSString *longConnect = [NSString stringWithFormat:@"123%f",version];
NSData *data = [longConnect dataUsingEncoding:NSUTF8StringEncoding];
[self.clientSocket writeData:data withTimeout:- 1 tag:0];
}