0

我的 websocket 服务器出现问题,无法从 websocket 客户端获取消息。据我了解,对于 ws 连接,客户端发送升级命令,服务器使用 Switching 协议状态代码和 Accept-Key 对其进行响应。我根据下面的代码实现了这个:

final class DummyHandler: ChannelInboundHandler {
    typealias InboundIn = HTTPServerRequestPart
    typealias OutboundOut = HTTPServerResponsePart

    func channelRead(context: ChannelHandlerContext, data: NIOAny) {
        print("channelRead called ....")

        let part = self.unwrapInboundIn(data)
        switch part {
                case .head(let header):
                    if(header.headers.contains(name: "Sec-WebSocket-Key"))
                    {
                        let acceptKey = calculateAcceptKey(inKey: header.headers["Sec-WebSocket-Key"][0])
                        
                        var headers = HTTPHeaders()
                        headers.add(name: "Upgrade", value: "websocket")
                        headers.add(name: "Connection", value: "Upgrade")
                        headers.add(name: "Sec-WebSocket-Accept", value: acceptKey!)
                        let responseHead = HTTPResponseHead(version: .init(major: 1, minor: 1), status: .switchingProtocols, headers: headers)
                        print(responseHead)
                        context.write(self.wrapOutboundOut(.head(responseHead)), promise: nil)
                        context.flush()
                    }
                    

                // ignore incoming content to keep it micro :-)
                case .body:
                    print("body")
                    break
                case .end:
                    print("End")
                    break
              }

    }
    
    func calculateAcceptKey(inKey: String) -> String?
    {
        if(inKey != nil)
        {
            let input = inKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
            let result = input.sha1()
            return result
        }
        return nil
    }
}

和服务器根据:

class Server {
    // MARK: - Initializers
    init(host: String, port: Int) {
        self.host = host
        self.port = port
    }
    
    // MARK: - Public functions
    func start() {
        do {
            print("server is starting .........")
            let bootstrap = NIOTSListenerBootstrap(group: group)
                
                .childChannelInitializer { channel in
                    channel.pipeline.configureHTTPServerPipeline()
                        .flatMap {
                            channel.pipeline.addHandler(DummyHandler())
                    }
                }
                
            let channel = try bootstrap
                .bind(host: host, port: port)
                .wait()
            
            try channel.closeFuture.wait()
        } catch {
            print("An error happed \(error.localizedDescription)")
            exit(0)
        }
    }
    
    func myTLSOptions() -> NWProtocolTLS.Options {
        let options = NWProtocolTLS.Options()
        let yourSecIdentity = getIdentity(password: "xxxx")// you have to implement something here
        sec_protocol_options_set_peer_authentication_required(options.securityProtocolOptions, false)
        sec_identity_create(yourSecIdentity!)
        return options
    }
    
    func getIdentity (password : String?) -> SecIdentity? {
        // Load certificate file
        let path = Bundle.main.url(forResource: "cert.p12", withExtension: nil, subdirectory: "/file")
        print(path)
        //let fileUrl = URL(string: path!)!
        let data = try! Data.init(contentsOf: path!)
        
        let options = [ kSecImportExportPassphrase as String: password ]
        var rawItems: CFArray?
        let status = SecPKCS12Import(data as CFData,
                                     options as CFDictionary,
                                     &rawItems)
        guard status == errSecSuccess else {
            print("Failed")
            return nil
            
        }
        let items = rawItems! as! Array<Dictionary<String, Any>>
        let firstItem = items[0]
        let identity = firstItem[kSecImportItemIdentity as String] as! SecIdentity?
        print(identity)
        return identity
    }
    
    func stop() {
        do {
            try group.syncShutdownGracefully()
        } catch {
            print("An error happed \(error.localizedDescription)")
            exit(0)
        }
    }
    
    // MARK: - Private properties
    private let group = NIOTSEventLoopGroup()
    private var host: String
    private var port: Int
}

我通过这个站点测试我的代码:http: //livepersoninc.github.io/ws-test-page/?

该站点正确打开了套接字,并且站点中的状态更改为已连接,但是在点击发送消息后,我的服务器中没有任何反应,并且我无法收到任何消息。如果有人指导我错过了什么,我将不胜感激。

4

0 回答 0