ios开发长连接,app长连接

iOS 必知必会 - APNs篇

导语:

创新互联专注为客户提供全方位的互联网综合服务,包含不限于成都网站制作、成都网站设计、克井网络推广、成都微信小程序、克井网络营销、克井企业策划、克井品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们最大的嘉奖;创新互联为所有大学生创业者提供克井建站搭建服务,24小时服务热线:028-86922220,官方网址:www.cdcxhl.com

由于移动设备内存、CPU、电量的局限性,iOS 不允许 APP 的进程常驻后台(事实上可以申请后台运行一段时间,最长约 10 分钟),这样当用户主动杀掉 APP,或者 APP 进入后台超过约定时长时,就意味着该 APP 进程的结束。这在很大程度上保障了前台 APP 的流畅性,也延长了手机的使用时长,获得了较好的用户体验。但是这也意味着,服务器无法主动和用户交互(如推送实时消息等)。为了解决这个限制,苹果推出了 APNs,允许设备和服务器分别与苹果的推送通知服务器保持长连接状态。

iOS 的通知分为本地通知和远程通知。本地通知是由本地应用触发的,一般是基于时间的一种通知形式,如闹钟、待办事件等的提醒。远程通知是由开发商通过自己的服务器推送的一种通知形式,而 APNs 就是远程通知功能的核心。

关于远程推送,记住以下两点就够了:

这里就很清楚了,其实 APNs 的本质就是 服务器和客户端之间的中介 。当服务器需要给客户端推送消息时,先将消息发送给苹果服务器,再由苹果服务器找到对应设备推送下去。

那为什么还要走中介,不直接发送呢?因为这样做一个设备(即所有 APP )只需要和苹果的服务器建立一条长连接,而不需要每个 APP 都和服务器建立一条长连接。

可能有些人还是不太明白 APNs 的意义,觉得也只是将多个长连接变成了统一的一个长连接而已,有必要那么做吗?

很有必要!

我们来看下 Android 的推送现状就明白了。

Android 事实上也有类似于 APNs 的一套用于推送的服务,简称 GCM,即 Google Cloud Messaging。但由于 GCM 需要谷歌服务器的支持,在国内由于「墙」的原因基本不能使用。这下就热闹了,国内出现了一大堆第三方推送服务商,如华为推送、小米推送、极光推送等。APP 通过集成这些推送服务来实现推送功能,而这些推送服务为了保持自己的长连接不被杀死,采用了各种保活、唤醒手段,这也是 Android 手机使用不流畅的真凶。之前也有看到「 工信部要求国内安卓统一消息推送标准 」的新闻,工信部都这么重视,可见统一推送的意义非凡。

想要了解具体区别,可以参考这篇文章 「 国内 90%以上的 iOS 开发者,对 APNs 的认识都是错的 」。

不言而喻,当然是尽早升级 HTTP/2 协议了。

参考:

(完)

iOS应用中使用AsyncSocket库处理Socket通信的用法

用socket可以实现像QQ那样发送即时消息的功能。客户端和服务端需要建立长连接,在长连接的情况下,发送消息。客户端可以发送心跳包来检测长连接。

在iOS开发中使用socket,一般都是用第三方库AsyncSocket,不得不承认这个库确实很强大。下载地址CocoaAsyncSocket。

特性

AsyncSocket类是支持TCP的。

AsyncUdpSocket是支持UDP的。

AsyncSocket是封装了CFSocket和CFSteam的TCP/IP socket网络库。它提供了异步操作,本地cocoa类的基于delegate的完整支持。主要有以下特性:

队列的非阻塞的读和写,而且可选超时。你可以调用它读取和写入,它会当完成后告知你。

自动的socket接收。如果你调用它接收连接,它将为每个连接启动新的实例,当然,也可以立即关闭这些连接。

委托(delegate)支持。错误、连接、接收、完整的读取、完整的写入、进度以及断开连接,都可以通过委托模式调用。

基于run loop的,而不是线程的。虽然可以在主线程或者工作线程中使用它,但你不需要这样做。它异步的调用委托方法,使用NSRunLoop。委托方法包括socket的参数,可让你在多个实例中区分。

自包含在一个类中。你无需操作流或者socket,这个类帮你做了全部。

支持基于IPV4和IPV6的TCP流。

AsyncUdpSocket是UDP/IP socket网络库,包装自CFSocket。它的工作很像TCP版本,只不过是用于处理UDP的.。它包括基于非阻塞队列的发送接收操作,完整的委托支持,基于runloop,自包含的类,以及支持IPV4和IPV6。

使用AsyncSocket的时候可以做一层封装,根据需求提供几个接口出来。比如:连接、断开连接、发送消息等等。还有接受消息,接受到的消息可以通过通知、代理、block等传出去。

下面简单介绍一下对AsyncSocket使用.一般来说,一个用户只需要建立一个socket长连接,所以可以用单例类方便使用。

定义单列类:LGSocketServe

LGSocketServe.h

复制代码 代码如下:

//

// LGSocketServe.h

// AsyncSocketDemo

//

#import

#import "AsyncSocket.h"

@interface LGSocketServe : NSObject

+ (LGSocketServe *)sharedSocketServe;

@end

LGSocketServe.m

复制代码 代码如下:

//

// LGSocketServe.m

// AsyncSocketDemo

//

#import "LGSocketServe.h"

@implementation LGSocketServe

static LGSocketServe *socketServe = nil;

#pragma mark public static methods

+ (LGSocketServe *)sharedSocketServe {

@synchronized(self) {

if(socketServe == nil) {

socketServe = [[[self class] alloc] init];

}

}

return socketServe;

}

+(id)allocWithZone:(NSZone *)zone

{

@synchronized(self)

{

if (socketServe == nil)

{

socketServe = [super allocWithZone:zone];

return socketServe;

}

}

return nil;

}

@end

建立socket长连接

LGSocketServe.h

复制代码 代码如下:

@property (nonatomic, strong) AsyncSocket *socket; // socket

// socket连接

- (void)startConnectSocket;

LGSocketServe.m

//自己设定

#define HOST @"192.168.0.1"

#define PORT 8080

//设置连接超时

#define TIME_OUT 20

- (void)startConnectSocket

{

self.socket = [[AsyncSocket alloc] initWithDelegate:self];

[self.socket setRunLoopModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];

if ( ![self SocketOpen:HOST port:PORT] )

{

}

}

- (NSInteger)SocketOpen:(NSString*)addr port:(NSInteger)port

{

if (![self.socket isConnected])

{

NSError *error = nil;

[self.socket connectToHost:addr onPort:port withTimeout:TIME_OUT error:error];

}

return 0;

}

宏定义一下HOST、PORT、TIME_OUT,实现startConnectSocket方法。这个时候要设置一下AsyncSocket的代理AsyncSocketDelegate。当长连接成功之后会调用:

复制代码 代码如下:

- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port

{

//这是异步返回的连接成功,

NSLog(@"didConnectToHost");

}

心跳

LGSocketServe.h

复制代码 代码如下:

@property (nonatomic, retain) NSTimer *heartTimer; // 心跳计时器

LGSocketServe.m

- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port

{

//这是异步返回的连接成功,

NSLog(@"didConnectToHost");

//通过定时器不断发送消息,来检测长连接

self.heartTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(checkLongConnectByServe) userInfo:nil repeats:YES];

[self.heartTimer fire];

}

// 心跳连接

-(void)checkLongConnectByServe{

// 向服务器发送固定可是的消息,来检测长连接

NSString *longConnect = @"connect is here";

NSData *data = [longConnect dataUsingEncoding:NSUTF8StringEncoding];

[self.socket writeData:data withTimeout:1 tag:1];

}

在连接成功的回调方法里,启动定时器,每隔2秒向服务器发送固定的消息来检测长连接。(这个根据服务器的需要就可以了)

断开连接

1,用户手动断开连接

LGSocketServe.h

复制代码 代码如下:

// 断开socket连接

-(void)cutOffSocket;

LGSocketServe.m

-(void)cutOffSocket

{

self.socket.userData = SocketOfflineByUser;

[self.socket disconnect];

}

cutOffSocket是用户断开连接之后,不在尝试重新连接。

2,wifi断开,socket断开连接

LGSocketServe.m

复制代码 代码如下:

- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err

{

NSLog(@" willDisconnectWithError %ld err = %@",sock.userData,[err description]);

if (err.code == 57) {

self.socket.userData = SocketOfflineByWifiCut;

}

}

wifi断开之后,会回调onSocket:willDisconnectWithError:方法,err.code == 57,这个时候设置self.socket.userData = SocketOfflineByWifiCut。

重新连接

socket断开之后会回调:

LGSocketServe.m

复制代码 代码如下:

- (void)onSocketDidDisconnect:(AsyncSocket *)sock

{

NSLog(@"7878 sorry the connect is failure %ld",sock.userData);

if (sock.userData == SocketOfflineByServer) {

// 服务器掉线,重连

[self startConnectSocket];

}

else if (sock.userData == SocketOfflineByUser) {

// 如果由用户断开,不进行重连

return;

}else if (sock.userData == SocketOfflineByWifiCut) {

// wifi断开,不进行重连

return;

}

}

在onSocketDidDisconnect回调方法里面,会根据self.socket.userData来判断是否需要重新连接。

发送消息

LGSocketServe.h

复制代码 代码如下:

// 发送消息

- (void)sendMessage:(id)message;

LGSocketServe.m

//设置写入超时 -1 表示不会使用超时

#define WRITE_TIME_OUT -1

- (void)sendMessage:(id)message

{

//像服务器发送数据

NSData *cmdData = [message dataUsingEncoding:NSUTF8StringEncoding];

[self.socket writeData:cmdData withTimeout:WRITE_TIME_OUT tag:1];

}

//发送消息成功之后回调

- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag

{

}

发送消息成功之后会调用onSocket:didWriteDataWithTag:,在这个方法里可以进行读取消息。

接受消息

LGSocketServe.m

复制代码 代码如下:

//设置读取超时 -1 表示不会使用超时

#define READ_TIME_OUT -1

#define MAX_BUFFER 1024

//发送消息成功之后回调

- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag

{

//读取消息

[self.socket readDataWithTimeout:-1 buffer:nil bufferOffset:0 maxLength:MAX_BUFFER tag:0];

}

//接受消息成功之后回调

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag

{

//服务端返回消息数据量比较大时,可能分多次返回。所以在读取消息的时候,设置MAX_BUFFER表示每次最多读取多少,当data.length MAX_BUFFER我们认为有可能是接受完一个完整的消息,然后才解析

if( data.length MAX_BUFFER )

{

//收到结果解析...

NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];

NSLog(@"%@",dic);

//解析出来的消息,可以通过通知、代理、block等传出去

}

[self.socket readDataWithTimeout:READ_TIME_OUT buffer:nil bufferOffset:0 maxLength:MAX_BUFFER tag:0];

接受消息后去解析,然后可以通过通知、代理、block等传出去。在onSocket:didReadData:withTag:回调方法里面需要不断读取消息,因为数据量比较大的话,服务器会分多次返回。所以我们需要定义一个MAX_BUFFER的宏,表示每次最多读取多少。当data.length MAX_BUFFER我们认为有可能是接受完一个完整的消息,然后才解析 。

出错处理

LGSocketServe.m

复制代码 代码如下:

- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err

{

NSData * unreadData = [sock unreadData]; // ** This gets the current buffer

if(unreadData.length 0) {

[self onSocket:sock didReadData:unreadData withTag:0]; // ** Return as much data that could be collected

} else {

NSLog(@" willDisconnectWithError %ld err = %@",sock.userData,[err description]);

if (err.code == 57) {

self.socket.userData = SocketOfflineByWifiCut;

}

}

}

socket出错会回调onSocket:willDisconnectWithError:方法,可以通过unreadData来读取未来得及读取的buffer。

使用

导入#import “LGSocketServe.h”

复制代码 代码如下:

LGSocketServe *socketServe = [LGSocketServe sharedSocketServe];

//socket连接前先断开连接以免之前socket连接没有断开导致闪退

[socketServe cutOffSocket];

socketServe.socket.userData = SocketOfflineByServer;

[socketServe startConnectSocket];

//发送消息 @"hello world"只是举个列子,具体根据服务端的消息格式

[socketServe sendMessage:@"hello world"];

ios开发中怎么通过socket长连接把请求下来的接口进行数据解析

创建一个缓冲区(字节数组)用于接收接收到的数据。每次接收到数据,就把数据追加到缓冲区中,然后判断缓冲区内数据是否符合要求。如果符合要求,把符合要求的数据从缓冲区中取出来,供应用程序使用,余下的数据仍然留在缓冲区中。如果不符合要求,那么继续接收。

ios 怎么与服务器建立长连接

app在前台的时候,使用tcp,自定义协议。 在后台的时候,断开连接,使用apn提示用户,唤醒app到前台后,重新连接,拉取离线消息。 im类的都是需要考虑消息到达速度,到达率,流量控制的。 消息数据越小,在相同网络情况下,耗时就少,速度就快。...

IOS的 推送 和 长连接 的区别

1.散热问题,7.0系统明显在运行程序时比ios6 系列系统发热较明显。(认为应该是开发版的缘 故,以后肯定会得到优化) 2.在点开设置活文件夹时候,其放大镜效果略有不流畅的效果。希望在正式版和以后版本中可以 得到解决。 3.对于某些应用程序在 7.0系统中的存在:比如:(这是综合国行和港行机子所存在的所有bug) BUG 总结: 1.微信朋友圈中不能上传 相片里的图片,只能拍照发送,而且在朋友圈里发送文字时,屏幕上方 会遮挡住2行文字。 与好友进行微信聊天时 不存在任何问题。 2.QQ 与好友进行聊天时候。可以互相发送图片,但不能点击放大,点击图片后肯定会闪退的。 3.还有一些应用程序在访问系统设置的过程中。比如访问照片 或者 麦克风 的时候,有时候会出 现卡机的情况。(可耐心等待,或者长按HOME键 直到出现语音界面,会好。) 4.在滑动菜单或进入程序的时候 文字会有叠加现象。 5.时钟与时间不符合 重启就会改善。

当前名称:ios开发长连接,app长连接
网页网址:https://www.cdcxhl.com/article32/dsdppsc.html

成都网站建设公司_创新互联,为您提供搜索引擎优化网站设计公司网站维护品牌网站建设网站改版建站公司

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

营销型网站建设