问题
在正常握手完成后,服务器重启,客户端ping超时之后,触发重连事件。
控制台也打印了重连的信息,第一次重连没有成功,服务器拒绝重连,客户端“没有”收到信息,控制台打印了发送重连的请求,但是服务器端收不到。导致客户端一直去重连,服务器端一直没收到任何信息。相互陷入困境,各种查资料,看文档,各自都没有发现问题。
官方的文档也是相当少,都是大同小异
思路
看了不少文档,sdk文档,最后锁定在基层发送给服务器的到底是什么,重连究竟是如何实现的
最终发现,在SocketManager.swift
与 SocketIOStatus
文件中
open func connect() {
guard !status.active else {
DefaultSocketLogger.Logger.log("Tried connecting an already active socket", type: SocketManager.logType)
return
}
if engine == nil || forceNew {
addEngine()
}
status = .connecting
engine?.connect()
}
// MARK: Properties
/// - returns: True if this client/manager is connected/connecting to a server.
public var active: Bool {
return self == .connected || self == .connecting
}
public var description: String {
switch self {
case .connected: return "connected"
case .connecting: return "connecting"
case .disconnected: return "disconnected"
case .notConnected: return "notConnected"
}
}
在发送重连之时,会先把 status 状态 改为 connecting
status = .connecting
这就导致 guard !status.active else { return}
永远 return ,下面真正去发送连接的事件没有触发,本地只是在循化打印去重连的日志而已,进入假重连模式。
解决方法:
public var active: Bool {
return self == .connected //|| self == .connecting
}
关于收不到服务器发送的错误信息问题
经过跟踪发现,服务器返回的消息可能因为格式等问题的存在,拿到的信息在
NWConnection.State
case waiting(NWError)
在 waiting中,而Starscream框架中
guard let conn = connection else {
return
}
conn.stateUpdateHandler = { [weak self] (newState) in
switch newState {
case .ready:
self?.delegate?.connectionChanged(state: .connected)
case .waiting://此处需要修改
break
case .cancelled:
self?.delegate?.connectionChanged(state: .cancelled)
case .failed(let error):
self?.delegate?.connectionChanged(state: .failed(error))
case .setup, .preparing:
break
@unknown default:
break
}
}
可以看到 框架对于waiting的错误信息是不做处理的,所以看不到任何服务器的错误信息打印,由此可见,还是不能过度信任第三方框架的,此问题解决了三天,开始都没有想到是框架的问题希望后来者不用走过多的弯路。
解决方案
case .waiting(let error):
self?.delegate?.connectionChanged(state: .waiting(error))
在 WSEngine 、Transport
文件中分别修改如下
public enum ConnectionState {
case connected
case waiting(Error?)
case cancelled
case failed(Error?)
....
}
public func connectionChanged(state: ConnectionState) {
switch state {
....
case .waiting(let error):
broadcast(event: .error(error))
break
....
}
这样外面就能收到服务器的拒绝信息了