前言
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)
}
雖然改動并不大,但是從頭到尾閱讀源碼并解析著實費了一番功夫。
一些反思
第一,很多時候我們要用到別人造的輪子,在以往我會關注作者代碼的質量,以及組件的完善程度,和自身項目是否合適,這里的合適包括多個方面的考量,組件可維護性,對項目的入侵性,耦合性,等等。但是從未考慮過一個點就是這個輪子是不是存在先天的缺陷。先入為主的思想影響著我自然而然的認為既然作為官方組件肯定是沒有問題的經過妥善測試的。
這讓我在以后對于組件的挑選更需要慎重認真了解,以及警惕性。
第二,解決問題的過程中多次僵持,一度想要放棄換用其他基于同樣通訊協議下的組件。 很多時候情緒會影響我們寫代碼和調試,遇到問題應該冷靜,重新審視邏輯流程等等。切不可被情緒影響慌了手腳。 暫時性的放下手上的工作,休息幾分鐘深呼吸等等往往有奇效。
第三,很多時候問題往往藏在最不容易發覺的地方,特別是此次官方的源代碼出了問題。不應該抱著僥幸的想法。