【移动应用开发技术】怎么在iOS中实现WebSocket长链接_第1页
【移动应用开发技术】怎么在iOS中实现WebSocket长链接_第2页
【移动应用开发技术】怎么在iOS中实现WebSocket长链接_第3页
【移动应用开发技术】怎么在iOS中实现WebSocket长链接_第4页
【移动应用开发技术】怎么在iOS中实现WebSocket长链接_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】怎么在iOS中实现WebSocket长链接

今天就跟大家聊聊有关怎么在iOS中实现WebSocket长链接,可能很多人都不太了解,为了让大家更加了解,在下给大家总结了以下内容,希望大家根据这篇文章可以有所收获。WebSocketWebSocket是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在TCP之上,同HTTP一样通过TCP来传输数据,但是它和HTTP最大不同是:WebSocket是一种双向通信协议.由于项目需要创建一个聊天室,需要通过长链接,和后台保持通讯,进行聊天,并且实时进行热点消息的推送.目前Facebook的SocketRocket应该是目前最好的关于SocketRocket使用的框架了.而且简单易用.使用一般一个项目在启动后的某个时机会启动创建一个长链接,如果需要多个就多次创建.如果只要一个就可以封装为一个单例,全局使用.可以使用podpod管理库,在podfile中加入pod'SocketRocket'在使用命令行工具cd到当前工程安装podinstall导入头文件后即可使用.为求稳定,我的做法是copy的FaceBook里SocketRocket库到项目里.-->SocketRocket地址1.首先创建一个名为WebSocketManager的单例类,+(instancetype)shared;2.创建一个枚举,分别表示WebSocket的链接状态typedef

NS_ENUM(NSUInteger,WebSocketConnectType){

WebSocketDefault

=

0,

//初始状态,未连接,不需要重新连接

WebSocketConnect,

//已连接

WebSocketDisconnect

//连接后断开,需要重新连接

};3.创建连接//建立长连接

-

(void)connectServer;4.处理连接成功的结果;-(void)webSocketDidOpen:(RMWebSocket

*)webSocket;

//连接成功回调5.处理连接失败的结果-

(void)webSocket:(SRWebSocket

*)webSocket

didFailWithError:(NSError

*)error;//连接失败回调6.接收消息///接收消息回调,需要提前和后台约定好消息格式.

-

(void)webSocket:(SRWebSocket

*)webSocket

didReceiveMessageWithString:(nonnull

NSString

*)string7.关闭连接-

(void)webSocket:(SRWebSocket

*)webSocket

didCloseWithCode:(NSInteger)code

reason:(NSString

*)reason

wasClean:(BOOL)wasClean;///关闭连接回调的代理8.为保持长链接的连接状态,需要定时向后台发送消息,就是俗称的:心跳包.需要创建一个定时器,固定时间发送消息.9.链接断开情况处理:首先判断是否是主动断开,如果是主动断开就不作处理.如果不是主动断开链接,需要做重新连接的逻辑.具体代码如下:WebSocketManager.h中的代码#import

<foundation

foundation=""

h="">

#import

"RMWebSocket.h"

typedef

NS_ENUM(NSUInteger,WebSocketConnectType){

WebSocketDefault

=

0,

//初始状态,未连接

WebSocketConnect,

//已连接

WebSocketDisconnect

//连接后断开

};

@class

WebSocketManager;

@protocol

WebSocketManagerDelegate

<nsobject>

-

(void)webSocketManagerDidReceiveMessageWithString:(NSString

*)string;

@end

NS_ASSUME_NONNULL_BEGIN

@interface

WebSocketManager

:

NSObject

@property

(nonatomic,

strong)

RMWebSocket

*webSocket;

@property(nonatomic,weak)

id

<websocketmanagerdelegate

nbsp="">

delegate;

@property

(nonatomic,

assign)

BOOL

isConnect;

//是否连接

@property

(nonatomic,

assign)

WebSocketConnectType

connectType;

+(instancetype)shared;

-

(void)connectServer;//建立长连接

-

(void)reConnectServer;//重新连接

-

(void)RMWebSocketClose;//关闭长连接

-

(void)sendDataToServer:(NSString

*)data;//发送数据给服务器

@end

NS_ASSUME_NONNULL_END

</websocketmanagerdelegate>

</nsobject>

</foundation>WebSocketManager.m中的代码#import

"WebSocketManager.h"

@interface

WebSocketManager

()

<rmwebsocketdelegate>

@property

(nonatomic,

strong)

NSTimer

*heartBeatTimer;

//心跳定时器

@property

(nonatomic,

strong)

NSTimer

*netWorkTestingTimer;

//没有网络的时候检测网络定时器

@property

(nonatomic,

assign)

NSTimeInterval

reConnectTime;

//重连时间

@property

(nonatomic,

strong)

NSMutableArray

*sendDataArray;

//存储要发送给服务端的数据

@property

(nonatomic,

assign)

BOOL

isActivelyClose;

//用于判断是否主动关闭长连接,如果是主动断开连接,连接失败的代理中,就不用执行

重新连接方法

@end

@implementation

WebSocketManager

+(instancetype)shared{

static

WebSocketManager

*_instance

=

nil;

static

dispatch_once_t

onceToken;

dispatch_once(&onceToken,

^{

_instance

=

[[self

alloc]init];

});

return

_instance;

}

-

(instancetype)init

{

self

=

[super

init];

if(self){

self.reConnectTime

=

0;

self.isActivelyClose

=

NO;

self.sendDataArray

=

[[NSMutableArray

alloc]

init];

}

return

self;

}

//建立长连接

-

(void)connectServer{

self.isActivelyClose

=

NO;

self.webSocket.delegate

=

nil;

[self.webSocket

close];

_webSocket

=

nil;

//

self.webSocket

=

[[RMWebSocket

alloc]

initWithURL:[NSURL

URLWithString:@"/ws/token=88888888"]];

self.webSocket

=

[[RMWebSocket

alloc]

initWithURL:[NSURL

URLWithString:@"ws://:7272"]];

self.webSocket.delegate

=

self;

[self.webSocket

open];

}

-

(void)sendPing:(id)sender{

[self.webSocket

sendPing:nil

error:NULL];

}

#pragma

mark

#pragma

mark

-

socket

delegate

///开始连接

-(void)webSocketDidOpen:(RMWebSocket

*)webSocket{

NSLog(@"socket

开始连接");

self.isConnect

=

YES;

self.connectType

=

WebSocketConnect;

[self

initHeartBeat];///开始心跳

}

///连接失败

-(void)webSocket:(RMWebSocket

*)webSocket

didFailWithError:(NSError

*)error{

NSLog(@"连接失败");

self.isConnect

=

NO;

self.connectType

=

WebSocketDisconnect;

DLog(@"连接失败,这里可以实现掉线自动重连,要注意以下几点");

DLog(@"1.判断当前网络环境,如果断网了就不要连了,等待网络到来,在发起重连");

DLog(@"3.连接次数限制,如果连接失败了,重试10次左右就可以了");

//判断网络环境

if

(AFNetworkReachabilityManager.sharedMworkReachabilityStatus

==

AFNetworkReachabilityStatusNotReachable){

//没有网络

[self

noNetWorkStartTestingTimer];//开启网络检测定时器

}else{

//有网络

[self

reConnectServer];//连接失败就重连

}

}

///接收消息

-(void)webSocket:(RMWebSocket

*)webSocket

didReceiveMessageWithString:(NSString

*)string{

NSLog(@"接收消息

%@",string);

if

([self.delegate

respondsToSelector:@selector(webSocketManagerDidReceiveMessageWithString:)])

{

[self.delegate

webSocketManagerDidReceiveMessageWithString:string];

}

}

///关闭连接

-(void)webSocket:(RMWebSocket

*)webSocket

didCloseWithCode:(NSInteger)code

reason:(NSString

*)reason

wasClean:(BOOL)wasClean{

self.isConnect

=

NO;

if(self.isActivelyClose){

self.connectType

=

WebSocketDefault;

return;

}else{

self.connectType

=

WebSocketDisconnect;

}

DLog(@"被关闭连接,code:%ld,reason:%@,wasClean:%d",code,reason,wasClean);

[self

destoryHeartBeat];

//断开连接时销毁心跳

//判断网络环境

if

(AFNetworkReachabilityManager.sharedMworkReachabilityStatus

==

AFNetworkReachabilityStatusNotReachable){

//没有网络

[self

noNetWorkStartTestingTimer];//开启网络检测

}else{

//有网络

NSLog(@"关闭连接");

_webSocket

=

nil;

[self

reConnectServer];//连接失败就重连

}

}

///ping

-(void)webSocket:(RMWebSocket

*)webSocket

didReceivePong:(NSData

*)pongData{

NSLog(@"接受pong数据-->

%@",pongData);

}

#pragma

mark

-

NSTimer

//初始化心跳

-

(void)initHeartBeat{

//心跳没有被关闭

if(self.heartBeatTimer)

{

return;

}

[self

destoryHeartBeat];

dispatch_main_async_safe(^{

self.heartBeatTimer

=

[NSTimer

timerWithTimeInterval:10

target:self

selector:@selector(senderheartBeat)

userInfo:nil

repeats:true];

[[NSRunLoop

currentRunLoop]addTimer:self.heartBeatTimer

forMode:NSRunLoopCommonModes];

})

}

//重新连接

-

(void)reConnectServer{

if(self.webSocket.readyState

==

RM_OPEN){

return;

}

if(self.reConnectTime

>

1024){

//重连10次

2^10

=

1024

self.reConnectTime

=

0;

return;

}

WS(weakSelf);

dispatch_after(dispatch_time(DISPATCH_TIME_NOW,

(int64_t)(self.reConnectTime

*NSEC_PER_SEC)),

dispatch_get_main_queue(),

^{

if(weakSelf.webSocket.readyState

==

RM_OPEN

&&

weakSelf.webSocket.readyState

==

RM_CONNECTING)

{

return;

}

[weakSelf

connectServer];

//

CTHLog(@"正在重连");

if(weakSelf.reConnectTime

==

0){

//重连时间2的指数级增长

weakSelf.reConnectTime

=

2;

}else{

weakSelf.reConnectTime

*=

2;

}

});

}

//发送心跳

-

(void)senderheartBeat{

//和服务端约定好发送什么作为心跳标识,尽可能的减小心跳包大小

WS(weakSelf);

dispatch_main_async_safe(^{

if(weakSelf.webSocket.readyState

==

RM_OPEN){

[weakSelf

sendPing:nil];

}

});

}

//没有网络的时候开始定时

--

用于网络检测

-

(void)noNetWorkStartTestingTimer{

WS(weakSelf);

dispatch_main_async_safe(^{

weakSWorkTestingTimer

=

[NSTimer

scheduledTimerWithTimeInterval:1.0

target:weakSelf

selector:@selector(noNetWorkStartTesting)

userInfo:nil

repeats:YES];

[[NSRunLoop

currentRunLoop]

addTimer:weakSWorkTestingTimer

forMode:NSDefaultRunLoopMode];

});

}

//定时检测网络

-

(void)noNetWorkStartTesting{

//有网络

if(AFNetworkReachabilityManager.sharedMworkReachabilityStatus

!=

AFNetworkReachabilityStatusNotReachable)

{

//关闭网络检测定时器

[self

destoryNetWorkStartTesting];

//开始重连

[self

reConnectServer];

}

}

//取消网络检测

-

(void)destoryNetWorkStartTesting{

WS(weakSelf);

dispatch_main_async_safe(^{

if(weakSWorkTestingTimer)

{

[weakSWorkTestingTimer

invalidate];

weakSWorkTestingTimer

=

nil;

}

});

}

//取消心跳

-

(void)destoryHeartBeat{

WS(weakSelf);

dispatch_main_async_safe(^{

if(weakSelf.heartBeatTimer)

{

[weakSelf.heartBeatTimer

invalidate];

weakSelf.heartBeatTimer

=

nil;

}

});

}

//关闭长连接

-

(void)RMWebSocketClose{

self.isActivelyClose

=

YES;

self.isConnect

=

NO;

self.connectType

=

WebSocketDefault;

if(self.webSocket)

{

[self.webSocket

close];

_webSocket

=

nil;

}

//关闭心跳定时器

[self

destoryHeartBeat];

//关闭网络检测定时器

[self

destoryNetWorkStartTesting];

}

//发送数据给服务器

-

(void)sendDataToServer:(NSString

*)data{

[self.sendDataArray

addObject:data];

//[_webSocket

sendString:data

error:NULL];

//没有网络

if

(AFNetworkReachabilityManager.sharedMworkReachabilityStatus

==

AFNetworkReachabilityStatusNotReachable)

{

//开启网络检测定时器

[self

noNetWorkStartTestingTimer];

}

else

//有网络

{

if(self.webSocket

!=

nil)

{

//

只有长连接OPEN开启状态才能调

send

方法,不然会Crash

if(self.webSocket.readyState

==

RM_OPEN)

{

//

if

(self.sendDataArray.count

>

0)

//

{

//

NSString

*data

=

self.sendDataArray[0];

[_webSocket

sendString:data

error:NULL];

//发送数据

//

[self.sendDataArray

removeObjectAtInd

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论