首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >斯威夫特Network.framework WebSocket握手零返回

斯威夫特Network.framework WebSocket握手零返回
EN

Stack Overflow用户
提问于 2018-10-08 03:49:37
回答 2查看 1.6K关注 0票数 2

我正在尝试使用新的Network.framework连接到WebSocket,但是面对来自服务器的零握手响应。

(是的,我知道红蜘蛛是存在的,但它不支持网络接口之间用户交换的代理/移动性)

我的测试代码:

代码语言:javascript
复制
func beginTest() {

    let connection = NWConnection(host: "echo.websocket.org", port: 443, using: .tls)

    connection.stateUpdateHandler = { state in
        print("State:", state)
        switch state {
        case .ready:
            self.connectionReady(connection)
        default:
            break
        }
    }
    connection.start(queue: .main)
}

func connectionReady(_ connection: NWConnection) {

    let raw = """
    GET / HTTP/1.1
    Upgrade: websocket
    Connection: Upgrade
    Host: echo.websocket.org
    Origin: https://echo.websocket.org
    Sec-WebSocket-Key: s04nPqA7M6pQ3Lu2jRJLSQ==
    Sec-WebSocket-Version: 13
    """

    let rawData = raw.appending("\n\n\n").replacingOccurrences(of: "\n", with: "\r\n").data(using: .utf8)

    connection.send(content: rawData!, completion: .idempotent)

    connection.receiveMessage(completion: {data, context, bool, error in
        if let data = data {
            print("Received:", String(data: data, encoding: .utf8))
        }

        print("Error:", error)

        let hello = "Hello".data(using: .utf8)
        connection.send(content: hello, completion: .idempotent)
    })
}

它的零响应和连接被删除,而不是从服务器获得升级握手响应,下面是控制台日志:

代码语言:javascript
复制
State: preparing
State: ready
Received: nil
Error: nil
2018-10-08 11:38:57.314885+0800 SwiftNetworkTest[86448:3026660] [] nw_socket_handle_socket_event [C1.1:2] Socket SO_ERROR [54: Connection reset by peer]

有人能指导我如何使用苹果新Network.framework吗?我们会非常感激的!

Update1

  • 糟糕的是,我现在能够看到使用.ascii编码而不是.utf8的握手响应。
  • 但是我仍然有连接中断了Connection reset by peer。如何在升级到WebSocket后保留连接?
EN

回答 2

Stack Overflow用户

发布于 2018-11-05 13:28:09

您应该遵循Websocket准则,如何格式化Websocket发送的消息。

我觉得这是个很好的资源。我自己用的。

servers

票数 1
EN

Stack Overflow用户

发布于 2020-07-30 22:17:10

在阅读了文档之后:result

我像这样设置了经过身份验证的TLS连接:

代码语言:javascript
复制
    init(endpoint: NWEndpoint, interface: NWInterface?, passcode: String, delegate: BitfinexConnectionDelegate)
    {
        self.delegate            = delegate
        self.initiatedConnection = false

        let host = "api.bitfinex.com"
        let port = 443
        
        let options = NWProtocolTCP.Options()
        options.connectionTimeout = 15
        
        let tlsOptions = NWProtocolTLS.Options()
        sec_protocol_options_set_verify_block(
            tlsOptions.securityProtocolOptions,
            {
                (sec_protocol_metadata, sec_trust, sec_protocol_verify_complete) in
                
                let trust = sec_trust_copy_ref(sec_trust).takeRetainedValue()
                
                let pinner = FoundationSecurity()
                
                pinner.evaluateTrust(trust: trust, domain: host, completion:
                {
                    (state) in
                    
                    switch state
                    {
                    case .success:
                        sec_protocol_verify_complete(true)
                    case .failed(_):
                        sec_protocol_verify_complete(false)
                    }
                })
            }, queue
        )
        
        let parameters = NWParameters(tls: tlsOptions, tcp: options)
        let conn = NWConnection(host: NWEndpoint.Host.name(host, nil),
                                port: NWEndpoint.Port(rawValue: UInt16(port))!,
                                using: parameters
        )
        self.connection = conn
        
        startConnection()
    }

FoundationSecurity()块是一个简单的TLS计算

代码语言:javascript
复制
if SecTrustEvaluateWithError(trust, &error)
{
    completion(.success)
}
else
{
    completion(.failed(error))
}

一旦我的连接好了。我发送了一个像这样创建的数据对象。这取决于您要与之接口的API。

代码语言:javascript
复制
    private func prepareWebSocket() throws -> Data
    {
        let apiKey    = "API_KEY"
        let apiSecret = "API_SECRET"
        let authNonce = NonceProvider.sharedInstanse.nonce
        let authPayload = "AUTH\(authNonce)"
        
        
        let authenticationKey  = SymmetricKey(data: apiSecret.data(using: .ascii)!)
        let authenticationCode = HMAC<SHA384>.authenticationCode(for: authPayload.data(using: .ascii)!,
                                                                 using: authenticationKey
        )
        
        let authSig = authenticationCode.compactMap { String(format: "%02hhx", $0) }.joined()
        
        let payload: [String : Any] =
        [
            "event":       "auth",
            "apiKey" :     apiKey,
            "authSig":     authSig,
            "authPayload": authPayload,
            "authNonce":   authNonce
        ]

        return try JSONSerialization.data(withJSONObject: payload, options: .fragmentsAllowed)
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52695147

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档