开篇语:
很久以前使用的即时通讯工具SocketIO,由于其对websocket进行了深度的封装,它的协议已经变得很复杂,对于大多数开源的Java服务器代码是不兼容的。so,还是回归最原汁原味的websocket类库:SocketRocket 吧!
这个库由Facebook公司开源,可靠性还是有保障的。最近发布的版本是0.5.1,可以通过cocoapods安装。但是,未发布的代码显示,新的文件结构已经大量重构,文件数量大大增加(主要是把先前的功能拆分成了多个文件),同时修复了不少bug。所以,我建议还是直接下载源码,手动把源码导入到工程中。
接下来的代码也都是基于最新的GitHub源码写的,如果对0.5.1版本有冲突,还请抱歉。
使用:
SocketRocket虽然支持的功能非常全面,但是,例如心跳包发送、断线重连还需要自己实现。上代码:
HXSocketManager.h
#import
typedefenum: NSUInteger {
HXSocketStatusConnecting, // 正在连接
HXSocketStatusConnected, // 已连接
HXSocketStatusFailed, // 失败
HXSocketStatusClosedByServer, // 系统关闭
HXSocketStatusClosedByUser, // 用户关闭
HXSocketStatusReceived, // 接收消息
} HXSocketStatus;
@interfaceHXSocketManager :NSObject
/**
重连时间间隔,默认3秒钟
*/
@property(nonatomic, assign) NSTimeInterval overtime;
/**
重连次数,默认无限次 -- NSUIntegerMax
*/
@property(nonatomic, assign) NSUInteger reconnectCount;
/**
当前链接状态
*/
@property(nonatomic, assign) HXSocketStatus status;
+ (instancetype)sharedInstance;
/**
开始连接
*/
- (void)connect;
/**
关闭连接
*/
- (void)close;
/**
发送一条消息
@parammessage 消息体
*/
- (void)sendMessage:(NSString*)message;
@end
HXSocketManager.m
#import "HXSocketManager.h"
#import "SRWebSocket.h"
@interface HXSocketManager ()
@property(nonatomic, strong) SRWebSocket *webSocket;
@property(nonatomic, weak) NSTimer *timer;
@property(nonatomic, strong) NSTimer *pingTimer; //每10秒钟发送一次ping消息
@property(nonatomic, strong) NSString *urlString;
@property(nonatomic, assign) NSUInteger currentCount; //当前重连次数
@end
@implementation HXSocketManager
+ (instancetype)sharedInstance {
static dispatch_once_t onceToken;
static HXSocketManager *instance = nil;
dispatch_once(&onceToken,^{
instance = [[super allocWithZone:NULL] init];
instance.overtime = 3;
instance.reconnectCount = NSUIntegerMax;
instance.urlString = WSUrl;
// 开启ping定时器
instance.pingTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:instance selector:@selector(sendPingMessage) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:instance.pingTimer forMode:NSRunLoopCommonModes];
});
return instance;
}
+ (id)allocWithZone:(struct _NSZone *)zone{
return [self sharedInstance];
}
/**
开始连接
*/
- (void)connect {
//先关闭
[self.webSocket close];
self.webSocket.delegate = nil;
//后开启
self.webSocket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.urlString]]];
self.webSocket.delegate = self;
self.status = HXSocketStatusConnecting;
[self.webSocket open];
}
/**
关闭连接
*/
- (void)close {
[self.webSocket close];
self.webSocket = nil;
[self.timer invalidate];
self.timer = nil;
}
/**
重新连接
*/
- (void)reconnect {
if (self.currentCount < self.reconnectCount) {
//计数器+1
self.currentCount ++;
NSLog(@"%lf秒后进行第%zd次重试连接……",self.overtime,self.currentCount);
// 开启定时器
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:self.overtime target:self selector:@selector(connect) userInfo:nil repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
self.timer = timer;
}
else{
NSLog(@"重连次数已用完……");
if (self.timer) {
[self.timer invalidate];
self.timer = nil;
}
}
}
/**
发送一条消息
@param message 消息体
*/
- (void)sendMessage:(NSString *)message {
if (message) {
NSError *error;
[self.webSocket sendString: message error:&error];
if (error) {
NSLog(@"发送消息失败!");
}else
{
NSLog(@"消息已发送");
}
}
}
/**
发送ping消息
*/
- (void)sendPingMessage {
NSError *error;
[self.webSocket sendPing:[NSData data] error:&error];
if (error) {
NSLog(@"发送心跳包失败!");
}else
{
NSLog(@"发送心跳包");
}
}
#pragma mark - SRWebSocketDelegate
/**
Called when a frame was received from a web socket.
@param webSocket An instance of `SRWebSocket` that received a message.
@param string Received text in a form of UTF-8 `String`.
*/
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessageWithString:(NSString *)string {
NSLog(@"收到信息:%@",string);
}
/**
Called when a given web socket was open and authenticated.
@param webSocket An instance of `SRWebSocket` that was open.
*/
- (void)webSocketDidOpen:(SRWebSocket *)webSocket {
NSLog(@"已链接服务器:%@",webSocket.url);
//重置计数器
self.currentCount = 0;
self.status = HXSocketStatusConnected;
}
/**
Called when a given web socket encountered an error.
@param webSocket An instance of `SRWebSocket` that failed with an error.
@param error An instance of `NSError`.
*/
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error {
NSLog(@"链接失败:%@",error.localizedDescription);
self.status = HXSocketStatusFailed;
//尝试重新连接
[self reconnect];
}
/**
Called when a given web socket was closed.
@param webSocket An instance of `SRWebSocket` that was closed.
@param code Code reported by the server.
@param reason Reason in a form of a String that was reported by the server or `nil`.
@param wasClean Boolean value indicating whether a socket was closed in a clean state.
*/
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(nullable NSString *)reason wasClean:(BOOL)wasClean {
NSLog(@"链接已关闭:code:%zd reason:%@",code,reason);
if (code == SRStatusCodeNormal) {
self.status = HXSocketStatusClosedByUser;
}else
{
self.status = HXSocketStatusClosedByServer;
//尝试重新连接
[self reconnect];
}
}
/**
Called on receive of a ping message from the server.
@param webSocket An instance of `SRWebSocket` that received a ping frame.
@param data Payload that was received or `nil` if there was no payload.
*/
- (void)webSocket:(SRWebSocket *)webSocket didReceivePingWithData:(nullable NSData *)data {
NSLog(@"收到 Ping");
}
/**
Called when a pong data was received in response to ping.
@param webSocket An instance of `SRWebSocket` that received a pong frame.
@param pongData Payload that was received or `nil` if there was no payload.
*/
- (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(nullable NSData *)pongData {
NSLog(@"收到 Pong");
}
@end
完全自动化,你只需要关心发送消息、接收消息即可。
---------------------
作者:TheLittleBoy
来源:CSDN
原文:https://blog.csdn.net/thelittleboy/article/details/83993489
版权声明:本文为博主原创文章,转载请附上博文链接!