本文介绍使用GCDAsyncSocket来实现iOS端的socket,有关简易服务端的代码已经在上一篇文章中提到,这里不再赘述,将直接介绍如何实现客户端。

首先下载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的代码
});

(六十五)iOS的socket实现(GCDAsyncSocket)的更多相关文章

  1. 第三百六十五节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的基本查询

    第三百六十五节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的基本查询 1.elasticsearch(搜索引擎)的查询 elasticsearch是功能 ...

  2. Gradle 1.12用户指南翻译——第六十五章. Maven 发布(新)

    其他章节的翻译请参见:http://blog.csdn.net/column/details/gradle-translation.html翻译项目请关注Github上的地址:https://gith ...

  3. “全栈2019”Java第六十五章:接口与默认方法详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  4. 孤荷凌寒自学python第六十五天学习mongoDB的基本操作并进行简单封装4

    孤荷凌寒自学python第六十五天学习mongoDB的基本操作并进行简单封装4 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第十一天. 今天继续学习mongoDB的简单操作 ...

  5. OpenCV开发笔记(六十五):红胖子8分钟带你深入了解ORB特征点(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  6. 《手把手教你》系列技巧篇(六十五)-java+ selenium自动化测试 - cookie -下篇(详细教程)

    1.简介 今天这一篇,宏哥主要讲解:利用WebDriver 提供可以读取.添加和删除cookie 信息的相关操作方法.验证浏览器中是否存在某个cookie.原因是:因为基于真实的cookie 的测试是 ...

  7. FastAPI(六十五)实战开发《在线课程学习系统》基础架构的搭建

    在之前三篇,我们分享的就是需求的分析,基本接口的整理,数据库链接的配置.这次我们分享项目的基本框架,目录结构如下: common目录 通用的目录,一些通用的处理放在这里 models目录 数据库相关的 ...

  8. SpringBoot进阶教程(六十五)自定义注解

    在上一篇文章<SpringBoot进阶教程(六十四)注解大全>中介绍了springboot的常用注解,springboot提供的注解非常的多,这些注解简化了我们的很多操作.今天主要介绍介绍 ...

  9. 六十五、SAP中通过BREAK-POINT下断点,进行调试

    一.代码如下,有2个断点的按钮,可以可以写入BREAK-POINT人工断点 二.运行之后,程序会被断下来, 四个执行按钮,意思分别为:单步进入子程序,单步不进入子程序,返回外面,执行到断点处 三.我们 ...

随机推荐

  1. 手写JAVA虚拟机(二)——实现java命令行

    查看手写JAVA虚拟机系列可以进我的博客园主页查看. 我们知道,我们编译.java并运行.class文件时,需要一些java命令,如最简单的helloworld程序. 这里的程序最好不要加包名,因为加 ...

  2. 关于ES7中的async/await在客户端和服务端上的实践

    一.前言 在项目中经常遇到处理异步请求的情况,面对层层的嵌套,回调显示那么苍白无力: async / await是ES7的重要特性之一,也是目前社区里公认的优秀异步解决方案,既然这样就用上吧. 二.配 ...

  3. rhel7 配置普通用户使用sudo

    rhel服务器版本安装之后,默认创建的用户不能使用sudo.使用sudo,会提示 user1 is not in the sudoers file. This incident will be rep ...

  4. PHP 5 Calendar 函数

    PHP Calendar 简介 日历扩展包含了简化不同日历格式间的转换的函数. 它是基于 Julian Day Count(儒略日计数),是从公元前 4713 年 1 月 1 日开始计算的. 注释:如 ...

  5. Nginx之(一)Nginx是什么

    Nginx("engine x")是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器.由俄罗斯的程序设计师Igor Sysoev所开发,供俄国大 ...

  6. 安卓高级6 SnackBar

    引言 文/李牧羊(简书作者) 原文链接:http://www.jianshu.com/p/2654e6bda3b1 著作权归作者所有,转载请联系作者获得授权,并标注"简书作者". ...

  7. 永远不要在循环之外调用wait方法

    1. 前言 随着摩尔定律的失效,Amdahl定律成为了多核计算机性能发展的指导.对于现在的java程序员们来说,并发编程越来越重要和习以为常.很惭愧和恐慌的是我对java的并发编程一直是只知道概念,入 ...

  8. Linux SWAP 交换分区配置说明

    一.SWAP 说明1.1 SWAP 概述        当系统的物理内存不够用的时候,就需要将物理内存中的一部分空间释放出来,以供当前运行的程序使用.那些被释放的空间可能来自一些很长时间没有什么操作的 ...

  9. proc文件系统探索 之 以数字命名的目录

    在proc根目录下,以数字命名的目录表示当前一个运行的进程,目录名即为进程的pid.其内的目录和文件给出了一些关于该进程的信息. niutao@niutao-desktop:/proc/6584$ l ...

  10. Scala:访问修饰符、运算符和循环

    http://blog.csdn.net/pipisorry/article/details/52902234 Scala 访问修饰符 Scala 访问修饰符基本和Java的一样,分别有:privat ...