(六十五)iOS的socket实现(GCDAsyncSocket)
2015-06-22 19:27
453 查看
本文介绍使用GCDAsyncSocket来实现iOS端的socket,有关简易服务端的代码已经在上一篇文章中提到,这里不再赘述,将直接介绍如何实现客户端。
首先下载CocoaAsyncSocket框架,如果下载过iOS的XMPP框架,在Vendor中有这个框架,将框架导入工程,并包含其头文件GCDAsyncSocket.h。
①这是一个异步socket框架,在子线程中完成socket的连接和数据接收,通过代理的方式通知控制器,因此要成为它的代理,代理名为GCDAsyncSocketDelegate。
②创建GCDAsyncSocket对象,并且使之成为成员属性,该对象兼备了输入输出流的功能,后续需要使用。
我们在这里传入一个全局队列,让它工作在子线程,防止网络不畅时阻塞主线程。
③连接服务端,还是假设服务端在本地,端口为12345,使用socket的connectToHost方法连接:
4.1连接成功的代理:
4.2连接结束的代理:
4.3接收数据的代理:
特别注意此处,只有先在发送成功的代理中调用读取方法,才会调用读取的代理方法:
这里的tag是用于区分不同的消息的,在写一条消息的时候需要指定tag,通过不同的tag判断服务器返回的消息的类型。这里有两类消息,分别是登录消息和聊天消息,只有后者会被显示,reloadDataWithText是用于tableView显示数据的方法。
这里对数据处理起来很简单,只需要把data直接转化为NSString即可。
⑤发送一条消息:
使用socket的writeData方法,这里不需要指定消息的长度和缓冲区大小,十分方便,tag会被传入,在调用上面提到的代理方法(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag时会被传入,用于判断消息类型。
需要注意的是异步socket工作在子线程,如果要更新UI,必然会在socket的代理方法中调用更新UI的方法,这时更新UI的代码运行于子线程,不能立即刷新UI界面,因此应该把更新UI的函数放在主线程中执行:
首先下载CocoaAsyncSocket框架,如果下载过iOS的XMPP框架,在Vendor中有这个框架,将框架导入工程,并包含其头文件GCDAsyncSocket.h。
①这是一个异步socket框架,在子线程中完成socket的连接和数据接收,通过代理的方式通知控制器,因此要成为它的代理,代理名为GCDAsyncSocketDelegate。
②创建GCDAsyncSocket对象,并且使之成为成员属性,该对象兼备了输入输出流的功能,后续需要使用。
GCDAsyncSocket *_socket;
我们在这里传入一个全局队列,让它工作在子线程,防止网络不畅时阻塞主线程。
_socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
③连接服务端,还是假设服务端在本地,端口为12345,使用socket的connectToHost方法连接:
NSString *host = @"127.0.0.1"; int port = 12345; NSError *error = nil; [_socket connectToHost:host onPort:port error:&error]; if (error) { NSLog(@"%@",error); }④实现代理方法来获取数据:
4.1连接成功的代理:
-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{ NSLog(@"成功连接到%@:%d",host,port); }
4.2连接结束的代理:
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{ if (err) { NSLog(@"%@",err); } }
4.3接收数据的代理:
特别注意此处,只有先在发送成功的代理中调用读取方法,才会调用读取的代理方法:
这里的tag是用于区分不同的消息的,在写一条消息的时候需要指定tag,通过不同的tag判断服务器返回的消息的类型。这里有两类消息,分别是登录消息和聊天消息,只有后者会被显示,reloadDataWithText是用于tableView显示数据的方法。
这里对数据处理起来很简单,只需要把data直接转化为NSString即可。
// 数据成功发送到服务器 - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{ // 需要自己调用读取方法,socket才会调用代理方法读取数据 [_socket readDataWithTimeout:-1 tag:tag]; } - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{ switch (tag) { case LoginTag: break; case MsgTag:{ NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; [self reloadDataWithText:msg]; break; } default: break; } }
⑤发送一条消息:
使用socket的writeData方法,这里不需要指定消息的长度和缓冲区大小,十分方便,tag会被传入,在调用上面提到的代理方法(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag时会被传入,用于判断消息类型。
// 发送 iam:name 表示name登录 NSString *loginStr = @"iam:soulghost"; // 把string转成NSData NSData *data = [loginStr dataUsingEncoding:NSUTF8StringEncoding]; [_socket writeData:data withTimeout:-1 tag:LoginTag];
需要注意的是异步socket工作在子线程,如果要更新UI,必然会在socket的代理方法中调用更新UI的方法,这时更新UI的代码运行于子线程,不能立即刷新UI界面,因此应该把更新UI的函数放在主线程中执行:
dispatch_async(dispatch_get_main_queue(), ^{ // 更新UI的代码 });
相关文章推荐
- OC基础:类的扩展.协议 分类: ios学习 OC 2015-06-22 19:22 34人阅读 评论(0) 收藏
- OC基础:Date 分类: ios学习 OC 2015-06-22 19:16 158人阅读 评论(0) 收藏
- OC基础:block.字面量 分类: ios学习 OC 2015-06-22 19:08 155人阅读 评论(0) 收藏
- (六十四)iOS的socket实现(C+OC混合实现)
- (六十四)iOS的socket实现(C+OC混合实现)
- 【iOS】Mapkit的使用:地图显示、定位、大头针、气泡等
- iOS 观察者模式(KVO)的简单使用
- iOS开发之Xcode6之后不再自动创建Pch预编译文件
- IOS如何生成一枚精美的像素按钮
- IOS菜鸟的所感所思(十三)——数据的图形化
- iOS 的 XMPPFramework 简介
- 【IOS】类似美团向下展开式选项
- 设置IOS 6.0顶部导航条颜色,和全屏开启应用,横竖屏选择
- iOS开发之旅--揭秘Runtime机制
- iOS开发之旅--KVO监听对象底层原理
- iOS开发之旅--深入讲解Singleton(单例设计模式)
- 使用Xcode 7 beta免费真机调试iOS应用程序
- iOS 数据持久化五-Core Data
- iOS 数据持久化二-对象归档
- iOS 数据持久化一-属性列表 Plist