iOS使用GCDSocketManager实现长连接

作者: fou7 | 来源:发表于2016-04-24 17:05 被阅读12379次

貌似进入2016年就没再更新简书,把写作忘了。罪过。

OK,进入正题,开始今天的技术讲解。

太概念的知识网上有很多,我只做概括和快速并正确的使用。

Socket,即使用套接字连接,实际上是对TCP/UDP的再次封装。

在一般项目中,使用Socket的情况很少,一般都会使用http实现客户端与服务器端的通信。并且是单向的。

但http只能通过客户端向服务器端主动发送网络请求,服务器会对该次请求进行响应,回传给客户端一些数据。如果客户端不主动向服务器端发送网络请求,服务器端是不能主动向客户端做出请求/响应操作的。

所以,为了实现服务器端可以主动向客户端发送请求,我们使用Socket来实现这一需求。


上代码:
1、先到github下载一个非常牛逼的库,地址:https://github.com/robbiehanson/CocoaAsyncSocket

下载到本地后,有两个文件夹:GCD / RunLoop

我个人比较喜欢使用GCD文件。看你擅长哪个技术就选择哪个文件吧。原理都是相同的。

2、将你想使用的文件拖到项目中。

3、一般我们使用第三方库都不会直接使用第三库中某个类或方法,而是对第三方库进行再次封装。.h文件如图:


Snip20160424_21.png

GCDSocketManager是我封装第三方的一个封装类。
对外操作都靠这个类来完成。所以我使用了单例模式供全局使用。

4、.m文件


Snip20160424_23.png

几个需要注意的点:
(1)封装类必须要实现第三方库的GCDAsynSocketDelegate协议
(2)握手次数:客户端和服务器端每次连接传递消息都会校验,校验就会根据握手次数。(socket的原理不多说了)
(3)断开重连定时器:特别需要谨记的是只有当前项目在前台运行时才可以保持长连接的状态,当项目进入后台就会断开长连接,别问为什么。如果你想在程序进入后台扔可以接到服务器主动给你发送的消息,使用推送服务。定时器在这里的作用就是,在当前程序处于前台,如果socket连接失败了要让它自动重连。每隔一段时间让socket自动连接一次。为了运行效率着想,这个时间可以每次进行累加。
(4)重连次数:我的重连次数就是用于时间的累加,第一次连接不上就1秒后重连,第二次连接不上就2秒后重连,以此累加。

5、.m文件的具体实现

Snip20160424_24.png

继续下一个

Snip20160424_26.png

继续下一个

Snip20160424_27.png

继续下一个

Snip20160424_28.png

有连接成功,肯定也会有连接失败,以下是对失败事件的处理:

Snip20160424_29.png

继续下一个

Snip20160424_31.png

连接成功处理完了,连接失败也处理完了。
做事有始有终,有连接,自然也要有断开。

Snip20160424_32.png

好,以下是对代码的调用时机和代码的使用细节进行一些讲解。

(1)什么时候进行长连?
长连当然是用户登录成功之后需要进行长连。
程序从后台切换到前台也需要进行长连。
所以可以把进行连接的代码写在根控制器中。

(2)什么时候断开长连?
前面说过,程序进入后台是要断开的。所以在Application进入后台时调用的那个生命周期方法里写断开长连的代码。

(3)关于两句很重要的代码

Snip20160424_33.png

timeout,超时时间。根据实际需求去设置,我这里设置为-1。

tag:发送数据和读取数据的tag值一定不能设置成一样的。
为什么不能设置成一样的呢?举个例子。
在这里tag相当于一个通道,并且在这个通道中只能完成一件事情。
如果这个通道专门用来发送数据的,就给这个通道打个标签,标签值就是1吧。
如果这个通道专门用来读取数据的,就给这个通道打个标签,标签纸就是200把。
数值随便定义,只能你能确保两者的tag值不一样。

但还有一个细节需要注意。

Snip20160424_34.png

我在上图代码中再次调用了读取数据的代码,这里的tag值要始终保持一致。

那么在这里写这句代码有啥用呢?
在写这句代码前,我们已经在连接成功的代理方法中写了这句代码。
在上图的代理方法中我可以读取服务器响应的数据。
读取完这一次服务器响应的数据后,下一次服务器再次发送数据我们该怎么读取?
就是通过这句代码,所以在这里再写一次。
这样我们就可以保证每次服务器响应的数据,我们客户端都可以正常读取了。

6、心跳包
心跳包。。就是一个数据包。
每隔一段时间向服务器传输一次你的数据。
当然是使用定时器实现了。代码就不上了哈。
到这里,又出现了一个新问题。
刚才已经说了,程序在前台才能保持长连。
程序进入后台长连就断了。
那么,当程序在后台时依然需要每隔一段时间向服务器发送一次心跳包,这个需求,怎么实现?
请听下回讲解。

代码连接:http://www.jianshu.com/p/60fd4ae4cd74

相关文章

网友评论

  • 873f2bdd8114:为什么 [self.socket writeData:jsonData withTimeout:-1 tag:1];
    发送的数据后台当时没有收到,但是当我断开连接的时候后台就收到发送的消息了,接受后台发给客户端的消息是正常的
    fou7:@小固执 断开连接的时候是不触发发送消息的代码了,排查一下呗
  • 卓敦:楼主,有没有HTTP长连接的demo吗,我的后台用的是HTTP长连接,不是scoket
    kuai空调:@卓敦 单纯实现socket这样的长链接,http是做不到的。http1.1加入了keep alive是提供了链接复用的机制,在间隔很短的几个请求间不断开链接。但这不是真正意义上的长链接
    卓敦:@huber 加了,但是每次请求完就结束了,后台返回的信息也看不到
    fou7:@卓敦 HTTP长连接需要在header里加Connection:keep-alive
  • 9f309e503f12:楼主 留下qq
  • tb144135:程序进入锁屏状态,就是进入后台,在Application进入后台时调用的那个生命周期方法里写断开长连的代码,然后又要程序在后台时依然需要每隔一段时间向服务器发送一次心跳包,心跳包,不是保持连接的吗,感觉有些矛盾
  • alelaile:大佬 收藏了 坐等后续呢!!!!!
  • Mr卿:老铁 后续呢?
  • 0271fb6f797c:后续呢。。。怎么就讲一半
    fou7:@dong136279559 我不是把关键字写出来了吗?可以用搜索引擎去搜索啊,后台任务是1+1=2的东西,没啥可讲的了。
    0271fb6f797c:@huber 就只有几句话吗?能专门写个帖子给我们这些小白讲解下吗?谢谢了
    fou7:@dong136279559 后续再评论区说完了啊
  • 6be5e7a24898:来来来,666
  • 47200923d724:楼主还在吗?进入后台怎样保持长连接啊?很想听你讲后续
  • 翀鹰精灵:楼主 你好 可以加下QQ(2807338860 )吗 我现在遇到一个问题 ,想交流下 可以吗?
    fou7:@翀鹰女孩 什么问题?
  • c089a4eefc6b:后续呢?
    fou7:@尔东CCC 这段时间比较忙,有时间一定会写后续
  • 海边的1984_:小鸡崽子,别截图啊,用markdown里面的代码格式啊,你这样哥们粘贴不了
    大牛在郑州:@小小流浪的汉子 6666

本文标题:iOS使用GCDSocketManager实现长连接

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