iOS Socket.io二三事

Choice_發表於2017-12-13

前言

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

通過監聽特定事件來獲取伺服器的訊息,以及提交特定事件來提交資料至伺服器。值得一提的是提交資料支援二進位制資料dataString甚至是字典,支援的範圍十分廣泛。

一些值得注意的坑

  • 在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中,可以設定相應的extraHeaderscookies

  • 伺服器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)
    }
複製程式碼

雖然改動並不大,但是從頭到尾閱讀原始碼並解析著實費了一番功夫。

一些反思

第一,很多時候我們要用到別人造的輪子,在以往我會關注作者程式碼的質量,以及元件的完善程度,和自身專案是否合適,這裡的合適包括多個方面的考量,元件可維護性,對專案的入侵性,耦合性,等等。但是從未考慮過一個點就是這個輪子是不是存在先天的缺陷。先入為主的思想影響著我自然而然的認為既然作為官方元件肯定是沒有問題的經過妥善測試的。 這讓我在以後對於元件的挑選更需要慎重認真瞭解,以及警惕性。

第二,解決問題的過程中多次僵持,一度想要放棄換用其他基於同樣通訊協議下的元件。 很多時候情緒會影響我們寫程式碼和除錯,遇到問題應該冷靜,重新審視邏輯流程等等。切不可被情緒影響慌了手腳。 暫時性的放下手上的工作,休息幾分鐘深呼吸等等往往有奇效。

第三,很多時候問題往往藏在最不容易發覺的地方,特別是此次官方的原始碼出了問題。不應該抱著僥倖的想法。

相關文章