| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- //
- // QSLSocketManager.swift
- // QuickSearchLocation
- //
- // Created by Destiny on 2024/12/6.
- //
- import SocketRocket
- import Foundation
- enum QSLSocketStatus: UInt {
- case connecting // 正在连接
- case connected // 已连接
- case failed // 失败
- case closedByServer // 系统关闭
- case closedByUser // 用户关闭
- case received // 接收消息
- }
- protocol QSLSocketManagerDelegate: AnyObject {
- func socketDidReceiveMessage(with string: String)
- }
- class QSLSocketManager: NSObject, SRWebSocketDelegate {
-
- static let shared = QSLSocketManager()
-
- private var webSocket: SRWebSocket?
- private var timer: Timer?
- private var pingTimer: Timer? // 每10秒钟发送一次ping消息
- private var currentCount: UInt = 0 // 当前重连次数
-
- var delegate: QSLSocketManagerDelegate?
- var urlString: String = ""
- var overtime: TimeInterval = 3.0 // 重连时间间隔,默认3秒钟
- var reconnectCount: UInt = UInt.max // 重连次数,默认无限次
- var status: QSLSocketStatus = .connecting
-
- private override init() {
- super.init()
- let url = "\(QSLApi.prodWSUrl)/websocket/\(QSLBaseManager.shared.userModel.authToken)"
- self.urlString = url
- }
-
- // MARK: - Public Methods
-
- @objc func connect() {
- // 先关闭连接
- self.webSocket?.close()
- self.webSocket?.delegate = nil
-
- // 后开启连接
- if let url = URL(string: self.urlString) {
- self.webSocket = SRWebSocket(urlRequest: URLRequest(url: url))
- self.webSocket?.delegate = self
- }
-
- self.status = .connecting
- self.webSocket?.open()
- }
-
- func close() {
- self.webSocket?.close()
- self.webSocket = nil
- self.timer?.invalidate()
- self.timer = nil
- self.pingTimer?.invalidate()
- self.pingTimer = nil
- }
-
- func reconnect() {
- guard currentCount < reconnectCount else {
- print("重连次数已用完……")
- self.timer?.invalidate()
- self.timer = nil
- return
- }
-
- // 计数器 +1
- currentCount += 1
- print("\(overtime)秒后进行第\(currentCount)次重试连接……")
-
- // 开启定时器进行重连
- self.timer = Timer.scheduledTimer(timeInterval: overtime, target: self, selector: #selector(connect), userInfo: nil, repeats: false)
- RunLoop.current.add(self.timer!, forMode: .common)
- }
-
- func sendMessage(_ message: String) {
-
- do {
- try self.webSocket?.send(string: message)
- ///判断要不要弹引导用户去评价
- QSLGuideusersToCommentManager.commentShare.manageWhetherTriggerPopUpWindow(QSLGuideusersToCommentType.nonMember)
- print("消息已发送")
- } catch {
- print("发送消息失败!")
- }
- }
-
- @objc func sendPingMessage() {
- guard status == .connected else { return }
-
- do {
- try self.webSocket?.sendPing(nil)
- print("发送心跳包")
- } catch {
- print("发送心跳包失败!")
- }
- }
-
- // MARK: - SRWebSocketDelegate Methods
-
- func webSocket(_ webSocket: SRWebSocket, didReceiveMessageWith string: String) {
- delegate?.socketDidReceiveMessage(with: string)
-
- let locationMessage = QSLMapMessageModel.mapModel(from: string)
- switch locationMessage.cmd {
- case "d.refresh.friend.list":
- NotificationCenter.default.post(name: QSLNotification.QSLRefreshFriend, object: nil)
- break
- case "d.refresh.friend.message":
- NotificationCenter.default.post(name: QSLNotification.QSLRefreshMessage, object: nil)
- break
- case "d.refresh.friend.request":
- NotificationCenter.default.post(name: QSLNotification.QSLRefreshRequest, object: nil)
- break
- case "d.refresh.contact":
- NotificationCenter.default.post(name: QSLNotification.QSLRefreshContact, object: nil)
- break
- case "d.refresh.member":
- NotificationCenter.default.post(name: QSLNotification.QSLRefreshMember, object: nil)
- break
- default:
- break
- }
- print("收到信息:\(string)")
- }
-
- func webSocketDidOpen(_ webSocket: SRWebSocket) {
- print("已链接服务器:\(webSocket.url ?? URL(fileURLWithPath: ""))")
-
- // 重置计数器
- self.currentCount = 0
- self.status = .connected
-
- // 开启ping定时器
- self.pingTimer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(sendPingMessage), userInfo: nil, repeats: true)
- RunLoop.current.add(self.pingTimer!, forMode: .common)
- }
-
- func webSocket(_ webSocket: SRWebSocket, didFailWithError error: Error) {
- print("链接失败:\(error.localizedDescription)")
-
- self.status = .failed
-
- // 尝试重新连接
- reconnect()
- }
-
- func webSocket(_ webSocket: SRWebSocket, didCloseWithCode code: Int, reason: String?, wasClean: Bool) {
- print("链接已关闭:code:\(code) reason:\(String(describing: reason))")
-
- if code == 1000 {
- self.status = .closedByUser
- } else {
- self.status = .closedByServer
- reconnect()
- }
- }
-
- func webSocket(_ webSocket: SRWebSocket, didReceivePingWith data: Data?) {
- print("收到 Ping")
- }
-
- func webSocket(_ webSocket: SRWebSocket, didReceivePong pongData: Data?) {
- print("收到 Pong")
- }
- }
|