Starscream..

173 阅读3分钟

自定义协议

import Foundation

import Starscream


protocol HXWebSocketDelegate:AnyObject {

    // TODO: Receive

    func fetchReceiveEvent(_ content:@escaping(_ event: WebSocketEvent,_ client: WebSocketClient) -> Void)

    func fetchDidReceiveData(_ content:@escaping(_ socket: WebSocketClient,_ data: Data) -> Void)

    func fetchDidReceiveMessage(_ content:@escaping(_ socket: WebSocketClient,_ text: String) -> Void)

    // TODO: Option

    func fetchDidConnect(_ content:@escaping(_ socket: WebSocketClient) -> Void)

    func fetchDidDisconnect(_ content:@escaping(_ socket: WebSocketClient,_ error: Error?) -> Void)



    // TODO: Test

    func fetchDidScrollToPositionFinish(_ content:@escaping(Int) -> Void)

}

创建 sm


class sm {

    var hxWebsocket:WebSocket? = nil

    weak var ws_delegate:HXWebSocketDelegate? = nil


    // TODO: 闭包

    private var closureReceiveEvent:((WebSocketEvent,WebSocketClient) -> Void)? = nil

    private var closureDidReceiveMessage:((WebSocketClient,String) -> Void)? = nil

    private var closureReceiveData:((WebSocketClient,Data) -> Void)? = nil

    private var closureDidConnect:((WebSocketClient) -> Void)? = nil

    private var closureDidDisconnect:(socket:WebSocketClient,error:Error?)? = nil



    private var closureScrollToPosition:((Int) -> Void)? = nil



    private init() {}

    // TODO: 单例

        static let pro = sm()





    // TODO: connect

    func connectServer(_ websoc:WebSocket? = nil,_ delegateTarget:WebSocketDelegate) {

        if let webs = websoc {

            self.hxWebsocket = webs

            webs.delegate = delegateTarget

            webs.connect()

        }

        else {

            if let url = URL(string: "http://localhost:8080"){

                let request = URLRequest(url: url)

                self.hxWebsocket = WebSocket(request: request)

                self.hxWebsocket?.delegate = delegateTarget

                self.hxWebsocket?.connect()

            }

        }

    }



    /** SSL Pinning is also supported in Starscream.

    var request = URLRequest(url: URL(string: "ws://localhost:8080/")!)

    let pinner = FoundationSecurity(allowSelfSigned: true) // don't validate SSL certificates

    let socket = WebSocket(request: request, certPinner: pinner)



    var request = URLRequest(url: URL(string: "ws://localhost:8080/")!)

    let compression = WSCompression()

    let socket = WebSocket(request: request, compressionHandler: compression)



    socket = WebSocket(url: URL(string: "ws://localhost:8080/")!, protocols: ["chat","superchat"])

    //create a custom queue

    socket.callbackQueue = DispatchQueue(label: "com.vluxe.starscream.myapp")

    */



    // TODO: reconnect



    func reconnectServer(_ URLStr:String,_ delegateTarget:WebSocketDelegate){

        if let url = URL(string: URLStr),self.hxWebsocket == nil{

            let request = URLRequest(url: url)

            hxWebsocket = WebSocket(request: request)

            hxWebsocket?.delegate = delegateTarget

            hxWebsocket?.connect()

        }

    }



    // TODO: write(string: "Hi Server!")

    func writeOnText(_ text:String? = nil) {

        if let msgText = text {

            self.hxWebsocket?.write(string: msgText)

        }

    }



    func writeOnData(_ data:Data? = nil) {

        if let msgData = data {

            self.hxWebsocket?.write(data: msgData)

        }

    }



    // TODO: write(ping)

    func writeOnPing(){

        self.hxWebsocket?.write(ping: Data())

    }



    // TODO: write(pong)

    func writeOnPong(){

        self.hxWebsocket?.write(pong: Data())

    }



    // TODO: disconnect

    func dismissConnect(){

        self.hxWebsocket?.disconnect()

    }

}

遵循协议


extension sm:WebSocketDelegate,HXWebSocketDelegate {



    // 这个方法非代理方法

    func didScrollToPosition(_ point:Int){

        self.closureScrollToPosition?(point)

    }



    func didReceive(event: WebSocketEvent, client: WebSocketClient) {

        self.closureReceiveEvent?(event,client)

    }



    func websocketDidConnect(socket: WebSocketClient) {

        self.closureDidConnect?(socket)

    }



    func websocketDidDisconnect(socket: WebSocketClient, error: Error?) {

        self.closureDidDisconnect?(socket,error)

    }



    func websocketDidReceiveData(socket: WebSocketClient, data: Data) {

        self.closureReceiveData?(socket, data)

    }



    func websocketDidReceiveMessage(socket: WebSocketClient, text: String) {

        self.closureDidReceiveMessage?(socket,text)

    }





    func fetchReceiveEvent(_ content: @escaping (_ e:WebSocketEvent, _ w:WebSocketClient) -> Void) {

        if closureReceiveEvent == nil {

            closureReceiveEvent = { event,client in

                content(event, client)

            }

        }

    }



    func fetchDidReceiveData(_ content: @escaping (_ w:WebSocketClient,_ data:Data) -> Void) {

        if closureReceiveData == nil {

            closureReceiveData = { socket,data in

                content(socket, data)

            }

        }

    }



    func fetchDidReceiveMessage(_ content: @escaping (_ w:WebSocketClient,_ text:String) -> Void) {

        if closureDidReceiveMessage == nil {

            closureDidReceiveMessage = {socket,message in

                content(socket, message)

            }

        }

    }



    func fetchDidConnect(_ content: @escaping (_ w:WebSocketClient) -> Void) {

        if closureDidConnect == nil {

            closureDidConnect = { socket in

                content(socket)

            }

        }

    }



    func fetchDidDisconnect(_ content: @escaping (_ w:WebSocketClient, Error?) -> Void) {

        if closureDidDisconnect == nil {

            closureDidDisconnect = { socket,error in

                content(socket,error)

            }

        }

    }



    func fetchDidScrollToPositionFinish(_ content:@escaping(Int) -> Void) {

        // 这里只在创建闭包之前打印一次(once)

        print(closureScrollToPosition.debugDescription)



        if closureScrollToPosition == nil {

            closureScrollToPosition = { value in

                content(value)

            }

        }

    }



}

使用


class Usage {

    var isConnected:Bool = false

    func dispatchToUsage(){

        sm.pro.fetchDidScrollToPositionFinish { value in

            print(value)

        }

    }



    func fetchUsage(){

        //unowned 使用闭包前self不能为nil,也就是说Usage对象不能被释放,很适合SWIFTUI

        sm.pro.fetchReceiveEvent { [unowned self] e, w in

            switch e {

                case .connected(let headers):

                    isConnected = true

                    print("websocket is connected: \(headers)")

                case .disconnected(let reason, let code):

                    isConnected = false

                    print("websocket is disconnected: \(reason) with code: \(code)")

                case .text(let string):

                    print("Received text: \(string)")

                case .binary(let data):

                    print("Received data: \(data.count)")

                case .ping(_):

                    break

                case .pong(_):

                    break

                case .viabilityChanged(_):

                    break

                case .reconnectSuggested(_):

                    break

                case .cancelled:

                    isConnected = false

                case .error(let error):

                debugPrint(error.debugDescription)

                    isConnected = false

                    case .peerClosed:

                          break

                }

        }

        // 接收文本

        sm.pro.fetchDidReceiveMessage { w, text in


        }

        // 接收数据

        sm.pro.fetchDidReceiveData { w, data in


        }

        // 接收模块必须在连接模块之前

        sm.pro.connectServer(sm.pro.hxWebsocket, sm.pro)



        // 发送数据

        sm.pro.writeOnPing()

        //发送一个pong控制帧,Starscream会自动响应传入的ping 控制帧,这样你就不需要手动发送 pong

        sm.pro.writeOnPong()

        sm.pro.writeOnText("Hong")

        sm.pro.writeOnData("Hong".data(using: .utf8))

        // 禁用 respondToPingWithPong 来关闭自动 ping 响应。

        sm.pro.hxWebsocket?.respondToPingWithPong = false

    }

}

  • 调用 (通过button模拟websocket代理发方法)

private unowned var pro = sm.pro

    var body: some View {

        VStack {

            Text(" OK ")

                .foregroundColor(.black)

                .font(.title2)

            Button.init("O K") {

                // 3.button模拟循环调用

                pro.didScrollToPosition(999)

            }.font(.title)

                .foregroundColor(.blue)

        }

        // 1.添加回调

        let _ = Usage().dispatchToUsage()

        // 2.模拟调用代理方法

        let _ = pro.didScrollToPosition(666)

    }