当前位置: 首页 > 工具软件 > SocketRocket > 使用案例 >

SocketRocket --- iOS使用篇

从景曜
2023-12-01

开篇语:

很久以前使用的即时通讯工具SocketIO,由于其对websocket进行了深度的封装,它的协议已经变得很复杂,对于大多数开源的Java服务器代码是不兼容的。so,还是回归最原汁原味的websocket类库:SocketRocket 吧!

这个库由Facebook公司开源,可靠性还是有保障的。最近发布的版本是0.5.1,可以通过cocoapods安装。但是,未发布的代码显示,新的文件结构已经大量重构,文件数量大大增加(主要是把先前的功能拆分成了多个文件),同时修复了不少bug。所以,我建议还是直接下载源码,手动把源码导入到工程中。

接下来的代码也都是基于最新的GitHub源码写的,如果对0.5.1版本有冲突,还请抱歉。

使用:

SocketRocket虽然支持的功能非常全面,但是,例如心跳包发送、断线重连还需要自己实现。上代码:

HXSocketManager.h

#import <Foundation/Foundation.h>

typedef enum : NSUInteger {
    HXSocketStatusConnecting,      // 正在连接
    HXSocketStatusConnected,       // 已连接
    HXSocketStatusFailed,          // 失败
    HXSocketStatusClosedByServer,  // 系统关闭
    HXSocketStatusClosedByUser,    // 用户关闭
    HXSocketStatusReceived,        // 接收消息
} HXSocketStatus;

@interface HXSocketManager : NSObject

/**
 重连时间间隔,默认3秒钟
 */
@property(nonatomic, assign) NSTimeInterval overtime;

/**
 重连次数,默认无限次 -- NSUIntegerMax
 */
@property(nonatomic, assign) NSUInteger reconnectCount;

/**
 当前链接状态
 */
@property(nonatomic, assign) HXSocketStatus status;

+ (instancetype)sharedInstance;

/**
 开始连接
 */
- (void)connect;

/**
 关闭连接
 */
- (void)close;

/**
 发送一条消息
 
 @param message 消息体
 */
- (void)sendMessage:(NSString *)message;

@end

HXSocketManager.m

#import "HXSocketManager.h"
#import "SRWebSocket.h"

@interface HXSocketManager ()<SRWebSocketDelegate>

@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

完全自动化,你只需要关心发送消息、接收消息即可。

 

 类似资料: