【问题标题】:How to handle websocket "requests" and "responses" in Swift?如何在 Swift 中处理 websocket“请求”和“响应”?
【发布时间】:2020-04-12 21:43:48
【问题描述】:

想象一下我们有使用 websocket 的聊天服务。我们以 JSON 格式发送消息,属性为 request_id。服务器捕获我们的消息,将其保存到数据库并返回消息的id,方法是使用传递的request_id 将另一个数据发送回客户端。客户必须找出这个“响应”到底与什么“请求”相关,并将数据保存到本地数据库。

例如:

  1. 客户端发送消息:
{
  "request_id": "1st",
  "content": "first message"
}
  1. 服务器收到消息,保存并返回新消息的id
{
  "request_id": "1st",
  "message_id": 123242139857814
}

与 Alammofire(使用闭包)不同,Starscream 库不提供这种机制。我正在寻找与 CoreData 和 RxSwift 兼容的解决方案。如何在不丢失“请求”上下文的情况下处理服务器的“响应”?

【问题讨论】:

  • 您确定您了解 WebSocket 的工作原理吗?由于您在请求和响应中都有 request_id ,因此找到相关的没有问题,不是吗?
  • @Dialogue 是的,我是。我有 2 条消息(发送和接收)具有相同的 request_id,并且在收到新消息时我可以找到相关请求。这意味着我必须通过处理程序保留请求(或ids)。如何编写具有处理程序或属性的此类?你能给我这个语法的例子吗?
  • 是的,当然,下面是一个例子

标签: swift starscream


【解决方案1】:

有很多方法。例如,您可以使用下一个代码

class Mapping<T: Hashable, U: Hashable> {

    typealias ForwardKey = T
    typealias ForwardValue = U

    typealias ReverseKey = ForwardValue
    typealias ReverseValue = ForwardKey

    typealias KeyPair = (ForwardKey, ReverseKey?)
    typealias ValuePair = (ForwardValue, ReverseValue)

    private var forward: [AnyHashable: AnyHashable]
    private var reverse: [AnyHashable: AnyHashable]
    private let emptyHashable = AnyHashable("")

    init() {
        forward = [:]
        reverse = [:]
    }

    func insert(pair: KeyPair) {
        if let base = pair.1 {
            forward[pair.0] = base
            reverse[base] = pair.0
        } else {
            forward[pair.0] = emptyHashable
        }
    }

    func update(pair: KeyPair) {
        insert(pair: pair)
    }

    subscript(forward key: ForwardKey) -> ForwardValue? {
        return forward.first(where: { $0.key.hashValue == key.hashValue })?.value as? ForwardValue
    }

    subscript(reverse key: ReverseKey) -> ReverseValue? {
        if let result = reverse.first(where: { $0.key.hashValue == key.hashValue })?.value as? ReverseValue {
            return result
        }

        return forward.first(where: { $0.key.hashValue == key.hashValue })?.key as? ReverseValue
    }

}

struct Request: Hashable {
    let requestID: String
    let content: String

    func hash(into hasher: inout Hasher) {
        hasher.combine(requestID)
    }
}

struct Response: Hashable {
    let requestID: String
    let messageID: String

    func hash(into hasher: inout Hasher) {
        hasher.combine(requestID)
    }
}

class WebSocket {

    private var callback: ((Request, Response) -> ())?
    private let mapping = Mapping<Request, Response>()

    func request(_ request: Request, callback: @escaping (Request, Response) -> ()) {
        mapping.insert(pair: (request, nil))
        self.callback = callback

        // Send webSocket message
    }

    // WebSocketDelegate
    // Since you are using Starscream
    func websocketDidReceiveMessage(/*socket: WebSocketClient,*/ text: String) {
        // Parse text to Response
        let response = Response(requestID: "1", messageID: "2")

        if let req = mapping[reverse: response] {
            mapping.update(pair: (req, response))
            callback?(req, response)
        }
    }

}

let webSocket = WebSocket()

webSocket.request(Request(requestID: "1", content: "A")) { request, response in
    print(request) // Request(requestID: "1", content: "A")
    print(response) // Response(requestID: "1", messageID: "2")
}

webSocket.websocketDidReceiveMessage(text: "")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-27
    • 2013-06-22
    • 1970-01-01
    • 2011-02-23
    • 1970-01-01
    • 2021-12-02
    • 2013-06-19
    相关资源
    最近更新 更多