项目剖析01-swift WebSocket

已经很长一段时间没有总结项目了,正好最近完成项目第二版的改版(新项目完全是用swift写的),就把项目中一些有意义的知识块在此记录一下, 项目中有实时的交易需要展示,所以用到了socket长链接,我用的是Starscream这个第三方库,集成方法很简单去网站看看就知道。

  1. 先上代码
import UIKit
import Reachability
import Starscream
import zlib

let reachability = Reachability()! // 判断网络连接
let webSocket = WTWebsocket.shared
var reConnectTime = 0 // 设置重连次数
let reConnectMaxTime = 1000 // 设置最大重连次数
let reConnectIntervalTime: TimeInterval = 15 // 设置重连时间间隔(秒)
var websocketTimer: Timer? = nil
var reConnectSubscribeDict:[String : Any] = [:]
var page = "home"
var isReconnect = true

final class WTWebsocket: NSObject,WebSocketDelegate {
    
    var isPingBack = true
    var myWebsocket: WebSocket? = nil
    //  socket连接上函数
    func websocketDidConnect(socket: WebSocketClient) {
        //设置重连次数,解决无限重连问题
        reConnectTime = 0
        if reConnectSubscribeDict.count > 0 {
            self.subscribe(subscribeDict: reConnectSubscribeDict)
        }
        self.hearJump()
        if  websocketTimer == nil {
            websocketTimer = Timer.scheduledTimer(timeInterval: reConnectIntervalTime, target: self, selector: #selector(sendBrandStr), userInfo: nil, repeats: true)
        }
        isReconnect = true
    }
    //发送文字消息
    @objc func sendBrandStr(){
        self.checkPing()
        let json = getJSONStringFromDictionary(dictionary: ["topic":"PING"])
        SingletonSocket.sharedInstance.socket.write(string: json)
    }
    // 发送ping
    func hearJump() {
        let json = getJSONStringFromDictionary(dictionary: ["topic":"PING"])
        SingletonSocket.sharedInstance.socket.write(string: json)
    }
    //  socket断开执行函数
    func websocketDidDisconnect(socket: WebSocketClient, error: Error?) {
        //执行重新连接方法
        socketReconnect()
    }
    //  接收返回消息函数
    func websocketDidReceiveMessage(socket: WebSocketClient, text: String) {
    }
    func websocketDidReceiveData(socket: WebSocketClient, data: Data) {
        guard let newStr = String(data: data.gzipUncompress(), encoding: .utf8) else {return}
        if newStr == "PONG" {
            isPingBack = true
            return
        }
      // 处理收到的信息
    }
    // 添加注册
    func subscribe(subscribeDict: [String : Any]) {
        var subscribeDicts = subscribeDict
        reConnectSubscribeDict = subscribeDicts
        page = subscribeDicts["type"] as! String
        subscribeDicts.removeValue(forKey: "type")
        let json = getJSONStringFromDictionary(dictionary:
            subscribeDicts as NSDictionary)
        SingletonSocket.sharedInstance.socket.write(string: json)
    }
    //检测
    @objc func checkPing() {
        if !isPingBack {
            // 重新连接
            socketReconnect()
        }else {
            isPingBack = false
        }
    }
    //构造单例数据
    static let shared = WTWebsocket()
    private override init() {
    }
}
//socket 重连逻辑
func socketReconnect() {
    //判断网络情况,如果网络正常,可以执行重连
    if reachability.connection != .none {
        //设置重连次数,解决无限重连问题
        reConnectTime =  reConnectTime + 1
        if reConnectTime < reConnectMaxTime {
            //添加重连延时执行,防止某个时间段,全部执行
            let time: TimeInterval = 2.0
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + time) {
                SingletonSocket.sharedInstance.socket.connect()
                SingletonSocket.sharedInstance.socket.disconnect()
            }
        } else {
            //提示重连失败
        }
    } else {
        //提示无网络
    }
}
//socket主动断开,放在app进入后台时,数据进入缓存。app再进入前台,app出现卡死的情况
func socketDisConnect() {
    if !SingletonSocket.sharedInstance.socket.isConnected {
        websocketTimer?.invalidate()
        websocketTimer = nil
        SingletonSocket.sharedInstance.socket.disconnect()
    }
}
// initSocket方法
func initWebSocketSingle () {
    SingletonSocket.sharedInstance.socket.delegate = webSocket
}
//声明webSocket单例
class SingletonSocket {
    let socket:WebSocket = WebSocket(url: URL(string: AppURLHOST.SocketURL)!)
    class var sharedInstance : SingletonSocket{
        struct Static{
            static let instance:SingletonSocket = SingletonSocket()
        }
        if !Static.instance.socket.isConnected{
            Static.instance.socket.connect()
        }
        return Static.instance
    }
}
  1. 整个代码很简单,基本都有注释,大概聊一聊里面的一些关键点

    2.1 发送ping-俗称发送心跳,这个主要是判断socket是否断开,链接成功后每次间隔固定时间发送一次请求,然后在返回中修改isPingBack,在下一次发送请求前检查isPingBack判断上一次的请求是否返回,这样就可以判断socket是否断开,这个间隔时间可以自由设定,但是最好不要太短,太短有可能是socket连接了但是没有来得及返回。当然太长也不行,这可能导致发现socket断开不及时。

    2.2 app在后台需要断开socket,当 app重新进入前台需要重新连接。

func applicationWillResignActive(_ application: UIApplication) {
        //进入后台模式,主动断开socket,防止出现处理不了的情况
        if SingletonSocket.sharedInstance.socket.isConnected {
            reConnectTime = reConnectMaxTime
            socketDisConnect()
        }
    }
    func applicationDidBecomeActive(_ application: UIApplication) {
        //进入前台模式,主动连接socket
        //解决因为网络切换或链接不稳定问题,引起socket断连问题
        //如果app从无网络,到回复网络,需要执行重连
        if !isFirstApplicationDidBecomeActive {
            reConnectTime = 0
            socketReconnect()
            WTBasicConfigManager.shareDataSingle.getHash()
        }
        isFirstApplicationDidBecomeActive = false
    }

2.3 一定要设置最大重新连接的次数,不然app会无限重新连接

2.4 连接成功或者重连成功都需要对需要推送的数据进行一次网络请求,确保数据的准确性。

  1. 以上就是我在项目中使用WebSocket的方法,如果有错误或者不足之处还望指正,谢谢
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容