前言
Socket.io 是一个基于WebSocket协议的Socket组件。通过这个组件我们可以很容易实现基于Socket连接的功能,例如实时聊天,弹幕等等。
同时Socket.io也支持多平台,在iOS上为Swift编写。
实例
在Socket.io中分别有两个方法,提交和监听。 这两个方法在socket通信中对应的就是一来一回的数据传输。监听来自服务器的消息,以及提交本地客户端的操作到服务器。
- 提交
func emit(_ event: String, _ items: SocketData...)
- 监听
func on(_ event: String, callback: @escaping NormalCallback) -> UUID
通过监听特定事件来获取服务器的消息,以及提交特定事件来提交数据至服务器。值得一提的是提交数据支持二进制数据data
、String
甚至是字典,支持的范围十分广泛。
一些值得注意的坑
- 在Objective-C和Swift混编的时候,初始化需要的config参数是一个字典,字典Key无法自动补全,提供的可配置的Key在
SocketIOClientOption
枚举中。
/// Not so type safe way to create a SocketIOClient, meant for Objective-C compatiblity.
/// If using Swift it's recommended to use `init(socketURL: NSURL, options: Set<SocketIOClientOption>)`
///
/// - parameter socketURL: The url of the socket.io server.
/// - parameter config: The config for this socket.
public convenience init(socketURL: NSURL, config: NSDictionary?) {
self.init(socketURL: socketURL as URL, config: config?.toSocketConfiguration() ?? [])
}
//例如:
SocketIOClient* socket = [[SocketIOClient alloc] initWithSocketURL:url config:@{@"log": @YES, @"compress": @YES}];
复制代码
-
假如服务器设置了
namespace
,在初始化参数中为nsp
,并且value必须以/
开头。如:@"nsp":@"/chatroom"
。 -
在与服务器的授权验证中,如果使用了明文的token,即将授权token当作参数提交至服务器,应该设置
connectParams
。 -
如果授权验证在Cookies中或者Header中,可以设置相应的
extraHeaders
和cookies
。 -
服务器URL不需要带上Socket.io后缀,在组件内部会自动补全。直接设置为服务器地址即可。
-
设置监听事件必须在调用
connect
方法之前监听完毕,然后才能调用connect
方法。
我遇到的坑
一开始初始化并连接服务器,发现始终无法连接成功,初步认定有可能是授权不成功,遂与服务器调试,发现服务器在关闭授权的方法之后终于能够连接成功,但并无法收到消息。进一步调试发现并未进入服务器设置的Namespace中,最终确定Namespace的设置有问题,经过排查发现Namespace参数拼写并无问题。最后只能阅读源码,发现iOS平台上的组件连接的时候并未使用nsp参数,直接导致无法进入指定的Namespace,这也直接证明一开始的问题所在,由于服务器的授权验证放置在指定的Namespace中,连接一开始,并未进入指定的Namespace,直接导致授权无法通过,无法连接成功。
解决的办法就是只能改写源码:
open func engineDidOpen(reason: String) {
//插入
if reason == "Connect" {
joinNamespace(nsp)
}
//
DefaultSocketLogger.Logger.log(reason, type: SocketIOClient.logType)
}
复制代码
虽然改动并不大,但是从头到尾阅读源码并解析着实费了一番功夫。
一些反思
第一,很多时候我们要用到别人造的轮子,在以往我会关注作者代码的质量,以及组件的完善程度,和自身项目是否合适,这里的合适包括多个方面的考量,组件可维护性,对项目的入侵性,耦合性,等等。但是从未考虑过一个点就是这个轮子是不是存在先天的缺陷。先入为主的思想影响着我自然而然的认为既然作为官方组件肯定是没有问题的经过妥善测试的。 这让我在以后对于组件的挑选更需要慎重认真了解,以及警惕性。
第二,解决问题的过程中多次僵持,一度想要放弃换用其他基于同样通讯协议下的组件。 很多时候情绪会影响我们写代码和调试,遇到问题应该冷静,重新审视逻辑流程等等。切不可被情绪影响慌了手脚。 暂时性的放下手上的工作,休息几分钟深呼吸等等往往有奇效。
第三,很多时候问题往往藏在最不容易发觉的地方,特别是此次官方的源代码出了问题。不应该抱着侥幸的想法。