Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

socket-io-swift-code-parse #9

Open
yuhanle opened this issue Apr 10, 2019 · 0 comments
Open

socket-io-swift-code-parse #9

yuhanle opened this issue Apr 10, 2019 · 0 comments
Assignees
Labels

Comments

@yuhanle
Copy link
Owner

yuhanle commented Apr 10, 2019

Socket-IO-4879410

通信协议

未命名表单-pk-4886284

举个例子

04-/chat,110[\"Hello\",{\"key\":\"value\"}]

字段拆解:

  • 0:连接。必填

  • 4:占位长度,也就是说后面还有 3个 package。可选

  • -:分隔符,占位长度截止到 -。可选

  • /chat:nsp,表示这个是 chat 相关的消息。可选

  • ,:分隔符,nsp 截止标识。可选

  • 110:ack,标识这是 110 的 ack。可选,若无,标识为 -1

  • […]:携带的数据。可选

建立一个 socket 连接,在此基础上,可以 connect 任何一个 nsp,或者断开指定的 nsp,双方可以指定 nsp 发送消息。

ws://127.0.0.1/v1/conversation + "/match"

./match 就是对应的 nsp,在连接到 conversation 后,通过 nsp 把各种业务消息从结构上分离。

  • 整个过程中,仅需要建立一次连接

  • 服务端有房间的概念,维护这个房间里的用户,可通过 nsp 和 房间号向这个房间里广播消息

  • 然后监听消息和事件

  • 客户端主动连接后,可根据不同的业务设置不同的 nsp

  • 服务端给已连接的客户端分配好房间,双方只需要在这个房间内收发消息

0x01

本部分从 socket-io 的基本思路入手,结合实际使用场景,抽离出协议层和应用层耦合部分。

Engine

模块职责:基础功能实现,包括连接、断开、收发数据,可配置使用 polling 或者 wss 的方式通信

  • EngineClient
  • EnginePollable
  • EngineWebsocket

EnginePacketType 如下:

/// Represents the type of engine.io packet types.
@objc public enum SocketEnginePacketType : Int {
    /// Open message.
    case open

    /// Close message.
    case close

    /// Ping message.
    case ping

    /// Pong message.
    case pong

    /// Regular message.
    case message

    /// Upgrade message.
    case upgrade

    /// NOOP.
    case noop
}

或者你可以自己实现一个 Engine,如下:

class TestEngine : SocketEngineSpec {
    weak var client: SocketEngineClient?
    private(set) var closed = false
    private(set) var compress = false
    private(set) var connected = false
    var connectParams: [String: Any]? = nil
    private(set) var cookies: [HTTPCookie]? = nil
    private(set) var engineQueue = DispatchQueue.main
    var extraHeaders: [String: String]? = nil
    private(set) var fastUpgrade = false
    private(set) var forcePolling = false
    private(set) var forceWebsockets = false
    private(set) var polling = false
    private(set) var probing = false
    private(set) var sid = ""
    private(set) var socketPath = ""
    private(set) var urlPolling = URL(string: "http://localhost/")!
    private(set) var urlWebSocket = URL(string: "http://localhost/")!
    private(set) var websocket = false
    private(set) var ws: WebSocket? = nil

    required init(client: SocketEngineClient, url: URL, options: [String: Any]?) {
        self.client = client
    }

    func connect() {
        client?.engineDidOpen(reason: "Connect")
    }

    func didError(reason: String) { }
    func disconnect(reason: String) { }
    func doFastUpgrade() { }
    func flushWaitingForPostToWebSocket() { }
    func parseEngineData(_ data: Data) { }
    func parseEngineMessage(_ message: String) { }
    func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data], completion: (() -> ())?) { }
}

ACK

管理维护 ACK,如果某条消息需要 ACK 的话,发送时生成 ACK 相关信息,在收到 ACK 时更新这条消息的状态

  • AckEmitter

发送 ACK 和处理收到的 ACK

  • AckManager

管理 ACK,保留暂未收到 ACK 的消息和 Callback

Client

主要和业务连接,每一个 nsp 对应一个 Client 对象,最终被添加到 Manager 中管理。弱应用 Manager,调用其相关 API。

最主要的是维护和当前 nsp 相关的 EventHandler,在收到 Manager 派发的消息时做自己的处理。

  • Configuration

连接相关的配置参数

  • RawView

Clinet 中可以便利使用 Emitter 功能

Util

包含日志、基础类型定义、拓展功能以及 SSL,SocketStringReader 作为主要功能,便于浏览 String 的结果

Parse

构造消息包和解析,按照通信协议,将传输的数据解析成结构

Manager

连接 Client 和 Engine 的纽带,Engine 的所有消息,都会经过 Manger 的派发,再给其他的 Client 处理。

如下例

var manager: SocketManager!
var socket: SocketIOClient!
var engine: SocketEngine!

override func setUp() {
    super.setUp()

    manager = SocketManager(socketURL: URL(string: "http://localhost")!)
    socket = manager.defaultSocket
    engine = SocketEngine(client: manager, url: URL(string: "http://localhost")!, options: nil)

    socket.setTestable()
}
@yuhanle yuhanle added the iOS label Apr 10, 2019
@yuhanle yuhanle self-assigned this Apr 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant