美文网首页
IOS Websocket (一) Starscream实现We

IOS Websocket (一) Starscream实现We

作者: 孔雨露 | 来源:发表于2019-10-18 08:52 被阅读0次

    @TOC

    1.Starscream 简介

    1. Conforms to all of the base Autobahn test suite.
    2. Nonblocking. Everything happens in the background, thanks to GCD.
    3. TLS/WSS support.
    4. Compression Extensions support (RFC 7692)
    5. Simple concise codebase at just a few hundred LOC.
    • 什么是websocket:

    WebSocket protocolHTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。
    WebSocket API,浏览器和服务器只需要要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

    1. HTTP 第一次出现是 1991 年,它设计为一种请求/响应式的通讯机制。Web 浏览器用这种机制工作良好,用户请求 web 页,服务器返回内容。但某些时候,需要有新数据时不经过用户请求就通知用户——也就是,服务器推。
    2. HTTP 协议无法很好地解决推模型。在 websocket 出现前,web 服务通过一系列浏览器刷新机制来实现推模型,但效率无法让人满意。
    3. webSocket 实现了服务端推机制。新的 web 浏览器全都支持 WebSocket,这使得它的使用超级简单。通过 WebSocket 能够打开持久连接,大部分网络都能轻松处理 WebSocket 连接。
    4. WebSocket 通常应用在某些数据经常性或频繁改变的场景。例如 Facebook 中的 web 通知、Slack 中的实时聊天、交易系统中的变化的股票价格
    • socket通讯过程:


      socket连接过程
    • 集成Websocket:

    开发中推荐使用Starscream框架。通过pod 方式导入:

     pod 'Starscream'
    
    • Starscream 使用swift版本为4.2

    2.Starscream 使用

    2.1 Starscream基本使用

     import UIKit
        import Starscream
       @objc public protocol DSWebSocketDelegate: NSObjectProtocol{
        /**websocket 连接成功*/
        optional func websocketDidConnect(sock: DSWebSocket)
        /**websocket 连接失败*/
        optional  func websocketDidDisconnect(socket: DSWebSocket, error: NSError?)
        /**websocket 接受文字信息*/
        func websocketDidReceiveMessage(socket: DSWebSocket, text: String)
        / **websocket 接受二进制信息*/
        optional  func  websocketDidReceiveData(socket: DSWebSocket, data: NSData)
        }
      public class DSWebSocket: NSObject,WebSocketDelegate {
        var socket:WebSocket!
        weak var webSocketDelegate: DSWebSocketDelegate?
        //单例
        class func sharedInstance() -> DSWebSocket
        {
            return manger
        }
        static let manger: DSWebSocket = {
            return DSWebSocket()
        }()
    
        //MARK:- 链接服务器
      func connectSever(){
        socket = WebSocket(url: NSURL(string: 你的URL网址如:ws://192.168.3.209:8080/shop))
        socket.delegate = self
        socket.connect()
       }
    
       //发送文字消息
       func sendBrandStr(brandID:String){
        socket.writeString(brandID))
      }
      //MARK:- 关闭消息
      func disconnect(){
          socket.disconnect()
      }
    
      //MARK: - WebSocketDelegate
      //客户端连接到服务器时,websocketDidConnect将被调用。
      public func websocketDidConnect(socket: WebSocket){
          debugPrint("连接成功了: \(error?.localizedDescription)")
          webSocketDelegate?.websocketDidConnect!(self)
      }
      //客户端与服务器断开连接后,将立即调用 websocketDidDisconnect。
      public func websocketDidDisconnect(socket: WebSocket, error: NSError?){
        debugPrint("连接失败了: \(error?.localizedDescription)")
        webSocketDelegate?.websocketDidDisconnect!(self, error: error)
      }
      //当客户端从连接获取一个文本框时,调用 websocketDidReceiveMessage。
      //注:一般返回的都是字符串
      public func websocketDidReceiveMessage(socket: WebSocket, text: String){
       debugPrint("接受到消息了: \(error?.localizedDescription)")
            webSocketDelegate?.websocketDidReceiveMessage!(self, text: text)
      }
      public func websocketDidReceiveData(socket: WebSocket, data: NSData){
        debugPrint("data数据")
        webSocketDelegate?.websocketDidReceiveData!(self, data: data)
          }
       }
    
    • 编写一个pong框架
      writePong方法与writePing相同,但发送一个pong控制帧。
    socket.write(pong: Data()) //example on how to write a pong control frame over the socket!
    

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

    但是,如果出于某些原因需要控制这个 prosses,你可以通过禁用 respondToPingWithPong 来关闭自动 ping 响应。

    socket.respondToPingWithPong=false//Do not automaticaly respond to incoming pings with pongs.
    

    当客户端从连接获得一个pong响应时,调用 websocketDidReceivePong。 你需要实现WebSocketPongDelegate协议并设置一个额外的委托,例如: socket.pongDelegate = self

    funcwebsocketDidReceivePong(socket: WebSocketClient, data: Data?) {
     print("Got pong! Maybe some data: (data?.count)")
    }
    

    2.2 Starscream高阶使用

    2.2.1 判断是否连接

    if socket.isConnected {
     // do cool stuff.
     }
    

    2.2.2 自定义头文件

    • 你可以使用自己自定义的web socket标头覆盖默认的web socket标头,如下所示:
    var request = URLRequest(url: URL(string: "ws://localhost:8080/")!)
    request.timeoutInterval = 5
    request.setValue("someother protocols", forHTTPHeaderField: "Sec-WebSocket-Protocol")
    request.setValue("14", forHTTPHeaderField: "Sec-WebSocket-Version")
    request.setValue("Everything is Awesome!", forHTTPHeaderField: "My-Awesome-Header")
    let socket = WebSocket(request: request)
    

    2.2.3 自定义HTTP方法

    • 你的服务器在连接到 web socket时可能会使用不同的HTTP方法:
    var request = URLRequest(url: URL(string: "ws://localhost:8080/")!)
    request.httpMethod = "POST"
    request.timeoutInterval = 5
    let socket = WebSocket(request: request)
    

    2.2.4 协议

    • 如果需要指定协议,简单地将它的添加到 init:
    //chat and superchat are the example protocols here
    socket = WebSocket(url: URL(string: "ws://localhost:8080/")!, protocols: ["chat","superchat"])
    socket.delegate = self
    socket.connect()
    

    2.2.5 自签名 SSL

    socket = WebSocket(url: URL(string: "ws://localhost:8080/")!, protocols: ["chat","superchat"])
    
    //set this if you want to ignore SSL cert validation, so a self signed SSL certificate can be used.
    socket.disableSSLCertValidation = true
    

    2.2.5.1 SSL引脚

    • Starscream还支持SSL固定。
    socket = WebSocket(url: URL(string: "ws://localhost:8080/")!, protocols: ["chat","superchat"])
    let data = ... //load your certificate from disk
    socket.security = SSLSecurity(certs: [SSLCert(data: data)], usePublicKeys: true)
    //socket.security = SSLSecurity() //uses the .cer files in your app's bundle
    

    你可以加载证书的Data 小区,否则你可以使用 SecKeyRef,如果你想要使用 public 键。 usePublicKeys bool是使用证书进行验证还是使用 public 键。 如果选择 usePublicKeys,将自动从证书中提取 public 密钥。

    2.2.5.2 SSL密码套件

    • 要使用SSL加密连接,你需要告诉小红你的服务器支持的密码套件。
    socket = WebSocket(url: URL(string: "wss://localhost:8080/")!, protocols: ["chat","superchat"])
    
    // Set enabled cipher suites to AES 256 and AES 128
    socket.enabledSSLCipherSuites = [TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256] 
    

    如果你不知道服务器支持哪些密码套件可以查看:SSL Labs

    2.2.6 压缩扩展

    • Starscream支持压缩扩展( RFC 7692 )。 默认情况下,压缩是启用的,但是只有当服务器支持压缩时才会使用压缩。 你可以通过 .enableCompression 属性启用或者禁用压缩:
    socket = WebSocket(url: URL(string: "ws://localhost:8080/")!)
    socket.enableCompression = false
    
    • 如果应用程序正在传输已经压缩。随机或者其他uncompressable数据,则应禁用压缩。

    2.2.7 自定义队列

    • 调用委托方法时可以指定自定义队列。 默认使用 DispatchQueue.main,因此使所有委托方法调用都在主线程上运行。 重要的是要注意,所有 web socket处理都是在后台线程上完成的,只有修改队列时才更改委托方法。 实际的处理总是在后台线程上,不会暂停你的应用程序。
    socket = WebSocket(url: URL(string: "ws://localhost:8080/")!, protocols: ["chat","superchat"])
    //create a custom queue
    socket.callbackQueue = DispatchQueue(label: "com.vluxe.starscream.myapp")
    

    2.2.8 高级代理

    socket.advancedDelegate = self
    
    • websocketDidReceiveMessage
    func websocketDidReceiveMessage(socket: WebSocketClient, text: String, response: WebSocket.WSResponse) {
        print("got some text: \(text)")
        print("First frame for this message arrived on \(response.firstFrame)")
    }
    
    • websocketDidReceiveData
    func websocketDidReceiveData(socket: WebSocketClient, data: Date, response: WebSocket.WSResponse) {
        print("got some data it long: \(data.count)")
        print("A total of \(response.frameCount) frames were used to send this data")
    }
    
    • websocketHttpUpgrade

    当发送HTTP升级请求后,会返回下面回调

    func  websocketHttpUpgrade(socket: WebSocketClient, request: CFHTTPMessage) {
        print("the http request was sent we can check the raw http if we need to")
    }
    
    func  websocketHttpUpgrade(socket: WebSocketClient, response: CFHTTPMessage) {
        print("the http response has returned.")
    }
    

    3.Starscream 使用Demo

    相关文章

      网友评论

          本文标题:IOS Websocket (一) Starscream实现We

          本文链接:https://www.haomeiwen.com/subject/dekbmctx.html