项目剖析01-swift WebSocket

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

先上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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
}
}

整个代码很简单,基本都有注释,大概聊一聊里面的一些关键点

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
}

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

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

以上就是我在项目中使用WebSocket的方法,如果有错误或者不足之处还望指正,谢谢

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2015-2025 kindyourself@163.com
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信