Facebook家的SocketRocket應(yīng)該是OC語(yǔ)言里針對(duì)WebSocket最好的框架啦淑廊,因?yàn)闃I(yè)務(wù)需求院尔,我們把應(yīng)用的部分請(qǐng)求更換成了長(zhǎng)鏈接,以下是使用總結(jié)锥忿。
至于為什么要使用WebSocket?當(dāng)然是為了與服務(wù)器更方便快捷地進(jìn)行通訊怠肋,不用每次請(qǐng)求都得客戶端先給服務(wù)器發(fā)一個(gè)Request敬鬓,然后等待服務(wù)器對(duì)應(yīng)的response;而可以由服務(wù)端決定什么時(shí)候給你推送什么消息笙各,這點(diǎn)對(duì)于某些通信類的功能模塊是很方便的钉答。
如果你想深入了解下Websocket的原理,可以看這篇WebSocket 是什么原理杈抢?為什么可以實(shí)現(xiàn)持久連接数尿?
接下來(lái)談?wù)刉ebSocket的使用,因?yàn)檎麄€(gè)SocketRocket就只有一個(gè).h和.m文件惶楼,所以socket的使用也相對(duì)簡(jiǎn)單右蹦。
1.首先建造一個(gè)SocketRocketUtility單例以便整個(gè)項(xiàng)目使用WebSocket來(lái)通信
@implementation SocketRocketUtility
+(SocketRocketUtility *)instance{
static SocketRocketUtility *Instance = nil;
static dispatch_once_t once;
dispatch_once(&once, ^{
Instance = [[SocketRocketUtility alloc]init];
}
}
2.然后創(chuàng)建一個(gè)Socket來(lái)建立通信
在.m文件中添加類的Extension
@interface SocketRocketUtility()<SRWebSocketDelegate>
@property (nonatomic, strong) SRWebSocket *socket;
@end
創(chuàng)建socket并建立連接
- (void) SRWebSocketOpen{
self.socket =[[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString: @"your string "]]];
self.socket.delegate = self;
[self.socket open];
}
-
然后處理socket連接的結(jié)果,監(jiān)聽(tīng)連接是否成功的回調(diào)
#pragma mark - socket delegate
如果連接建立成功
- (void)webSocketDidOpen:(SRWebSocket *)webSocket { //開(kāi)啟心跳 [self initHeartBeat]; if (webSocket == self.socket) { NSLog(@"************************** socket 連接成功************************** "); } }
如果連接建立失敗
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error { if (webSocket == self.socket) { NSLog(@"************************** socket 連接失敗************************** "); _socket = nil; //連接失敗就重連 [self reConnect]; } }
這里有個(gè)心跳規(guī)則歼捐,其實(shí)一般的Websocket的第三方框架會(huì)自帶這個(gè)并不需要自己做特別處理何陆,只要與服務(wù)器商量好時(shí)間,定時(shí)地向服務(wù)器發(fā)送ping消息豹储,服務(wù)器會(huì)返回相應(yīng)地pong消息贷盲,表示我們的連接還在
- (void) initHeartBeat{
heartBeat = [NSTimer timerWithTimeInterval:10 target:self selector:@selector(ping) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:heartBeat forMode:NSRunLoopCommonModes];
}
這里用了NSTimer,所以要注意對(duì)應(yīng)所在線程的runloop颂翼;正常情況下晃洒,將NSTimer添加到主線程的runloop中,為了確保這段代碼在主行程中執(zhí)行朦乏,我們添加一段宏
#define dispatch_main_async_safe(block)\
if ([NSThread isMainThread]) {\
block();\
} else {\
dispatch_async(dispatch_get_main_queue(), block);\
}
然后將上面的代碼改成
dispatch_main_async_safe(^{
heartBeat = [NSTimer timerWithTimeInterval:10 target:self selector:@selector(ping) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop]addTimer:heartBeat forMode:NSRunLoopCommonModes];
})
具體的ping方法就是調(diào)用第三方框提供的方法
- (void) ping{
if(self.socket.readyState == SR_OPEN){
[self.socket sendPing:nil];
}
}
4.就是想服務(wù)器發(fā)送數(shù)據(jù)球及,一般跟服務(wù)器通信傳遞的數(shù)據(jù)是json格式,所以記得把之前字典里的信息以及服務(wù)器要求的一些相關(guān)字段轉(zhuǎn)換成json格式呻疹,然后send:
- (void)sendData{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (weakself.socket != nil) {
// 只有 SR_OPEN 開(kāi)啟狀態(tài)才能調(diào) send 方法啊吃引,不然要崩
if (weakself.socket.readyState == SR_OPEN) {
[weakself.socket send:data]; // 發(fā)送數(shù)據(jù)
} else if (weakself.socket.readyState == SR_CONNECTING) {
[self reConnect];
} else if (weakself.socket.readyState == SR_CLOSING || weakself.socket.readyState == SR_CLOSED) {
// websocket 斷開(kāi)了,調(diào)用 reConnect 方法重連
[self reConnect];
}
}
else{
//如果在發(fā)送數(shù)據(jù)刽锤,但是socket已經(jīng)關(guān)閉镊尺,可以在再次打開(kāi)
[self SRWebSocketOpen];
}
});
}
5.接收服務(wù)器信息
#pragma mark - 收到的回調(diào)
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message {
if (webSocket == self.socket) {
NSLog(@"message:%@",message);
if(!message){
return;
}
//收到的數(shù)據(jù)格式也是json格式的,可以用MJExtension里字典轉(zhuǎn)模型的方法更改為自定義的數(shù)據(jù)格式
//這里要將接收到的消息專遞出去并思,可以用block或者通知的形式庐氮;個(gè)人偏好block一點(diǎn)
[self handleReceivedMessage:message];
}
}
6.關(guān)閉Socket連接
最后可以選擇在合適的時(shí)候關(guān)閉長(zhǎng)連接
-(void)SRWebSocketClose{
if (self.socket){
[self.socket close];
self.socket = nil;
//斷開(kāi)連接時(shí)銷毀心跳
[self destoryHeartBeat];
}
}
具體代碼在這里 WebsocketDemo-iOS
這里推薦一個(gè)可用的Websocket在線測(cè)試網(wǎng)站:http://www.blue-zero.com/WebSocket/
表示可以看看我的star,對(duì)于一個(gè)程序員宋彼,我star里面的東西還是蠻不錯(cuò)噠
- 參考文章 iOS Websocket接入