美文网首页
即时通讯之CocoaAsyncSocket使用(二)

即时通讯之CocoaAsyncSocket使用(二)

作者: 小歪子go | 来源:发表于2017-12-04 09:18 被阅读0次

一、简介

CocoaAsyncSocket是谷歌的开发者,基于BSD-Socket写的一个IM框架,可在github下载 ,它给Mac和iOS提供了易于使用的、强大的异步套接字库,向上封装出简单易用OC接口。省去了我们面向Socket以及数据流Stream等繁琐复杂的编程。其结构框架简介示意图如下:

image.png
整个库就这么两个类,一个基于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];
}

相关文章

网友评论

      本文标题:即时通讯之CocoaAsyncSocket使用(二)

      本文链接:https://www.haomeiwen.com/subject/erpibxtx.html