sockiet.io-client-swift
- 前言
问题 最近在做一个新项目时为了性能考虑,在获取一些变化比较频繁时使用websocket的方式进行订阅推送,在上一个项目时也使用了websocket,当时是直接使用了Facebook开源的SocketRocket,但在这次选型时不知道是什么原因,后台服务器选用了websocket的一个变种,socket.io,于是问题因此而产生,Android那边在网上使用了一个库后和服务器正常通信能收发数据,可是到我们iOS时,我们选用的是socket.io-client-swift,可是由于这个开源库的demo非常简单,导致我们在使用后和服务器建立连接后就一直相互收不了数据,一个同事很形象的比喻了下
双方用手机打电话,明明手机都通了,可是就是双方都说听不见对方
这一问题折磨了我那负责这一块的同事好多天后他都没解决,然后就尝试着让我解决,我接受后看了一个晚上也没什么进展,最后通过在同事的帮组下使用tcp-flow、tcp-flow抓包发送的数据,发现ping的心跳包能正常发送,但一旦发送请求的业务数据就只是在log区里显示发送成功,但实际拦截的数据却是只发送了一个状态码4,看到这里,我当时冒出了想法,既然能发送状态码,我固定发送些其他信息看看能不能发送,经过一番艰辛的努力,发现自己写的固定内容是能发送的,而一旦换成这个库自己生成的内容后就又只有状态码了,然后在写固定发送内容时后端的同事告诉我发送的内容还差一个namespace,再跟据这个情况最后发现了是这个库如果使用者没有手动设置namespace就会有一个默认的空namespace,然后由于兼容做的不好,导致发送的数据在解析成data时就解析没了,问题找到,然后按下面方式把问题解决
NSURL *url = [NSURL URLWithString:@"http://192.168.99.221:8000/socket.io/"];
SocketIOClient *socket = [[SocketIOClient alloc] initWithSocketURL:url config:@{@"log": @YES,@"forcePolling":@YES,@"forceWebsockets":@YES}];
socket.nsp = @"/socket.io/"
[socket connect];
[socket on:@"connect" callback:^(NSArray* data, SocketAckEmitter* ack) {
NSLog(@"socket connected");
[socket emit:@"sub" with:@[@"业务数据"]];
}];
[socket on:@"sub" callback:^(NSArray* data, SocketAckEmitter* ack) {
id obj = data.firstObject;
NSData *jsonData = [obj dataUsingEncoding:NSUTF8StringEncoding];
NSError *err;
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers
error:&err];
NSLog(@"%@",dic);
}];
这次解决问题的收获蛮多,
- 首先是了解并使用了tcp-flow、tcp-flow这个抓包神器,
- 另外就是认识到就是在使用第三方库时的风险所在,由于这个库的说明实在太简单,都没告诉要设置namespace的事,另外由于兼容实在做的有问题,在没有设置namespace时既不提示,还在发送数据时直接数据解析出差,业务数据发送不出去,只能有一个状态码发送出来,这个一会儿要去提一个issue
- 解决问题很多情况下靠思路,有了思路问题总能一步步解决,当然有时候运气也是很重要的,在同事看到我写的固定数据差一个namespace后我查找的范围也大大缩小了
- 对于技术选型,尽量不要太追新赶潮,稳定的能提高效率的才是最好的
- 由于对之前使用的SocketRocket和现在使用的socket.io都只是一知半解的一般使用,没有具体研究,现在立下一个flag,要把这两个库仔细研究一下然后反应成Objective-C