iOS 13 URLSessionWebSocketTask当前连接状态
我已经设置并实现了我的iOS 13 URLSessionWebSocketTask当前连接状态,ios,swift,websocket,urlsession,Ios,Swift,Websocket,Urlsession,我已经设置并实现了我的URLSessionWebSocketDelegate urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) 但是,只有在服务器正确断开连接的情况下,代理才会受到影响。如果连接断开或服务器未提供断开连接代码,则委托功能将永远不会运行。
URLSessionWebSocketDelegate
urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?)
但是,只有在服务器正确断开连接的情况下,代理才会受到影响。如果连接断开或服务器未提供断开连接代码,则委托功能将永远不会运行。我还尝试在断开连接之前和之后检查URLSessionWebSocketTask
属性closeCode
和closeReason
,除非服务器发送正确的断开连接代码,否则它们不会更改
虽然我可以控制服务器,并且可以确保故意断开连接有一个代码,但如果网络连接断开,会发生什么情况?或者如果服务器宕机?我认为委托函数仍然应该被调用
有趣的是,我的侦听函数得到一个错误,错误状态如下:
Error Domain=NSPOSIXErrorDomain Code=57 "Socket is not connected" UserInfo={NSErrorFailingURLStringKey=[urlomitted], NSErrorFailingURLKey=[urlomitted]
因此,虽然我可以在看到错误57时手动断开套接字,但我不知道这是否适用于所有不同的断开类型
我想我可能是做错了什么,或者这是一个bug,但我找不到其他有同样问题的人,所以我想在提交雷达之前询问一下。不确定这是一个好方法,但是下面两种解决方案都会在我的代码中捕获服务器/连接丢失事件 a) 您可以在WebSocket接收函数中检测到它,如下所示:
func receiveMessage() {
webSocketTask?.receive { result in
defer { self.receiveMessage() }
switch result {
case .failure(let error):
print("Error in receiving message: \(error)")
let code = (error as NSError).code
if code == 60 || code == 57 || code == 54 {
// deal with error
}
case .success(let message):
switch message {
case let .string(string):
// deal with strings message
case let .data(data):
// deal with data message
@unknown default:
// deal with unknown message
}
}
}
}
b) 或者,您可以将urlSession实例方法添加到URLSessionWebSocketDelegate
,该方法捕获服务器的一般丢失/连接错误
extension BlipSocket: URLSessionWebSocketDelegate {
func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?) {
DispatchQueue.main.async {
self.isConnected = true
}
}
func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) {
DispatchQueue.main.async {
self.isConnected = false
}
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError: Error?) {
DispatchQueue.main.async {
self.connectionError = true
}
}
}
您还可以实现
urlSession(\usession:urlSession,task:URLSessionTask,didcompletewitheror error:error?)
这是一个urlsessionelegate。这会在连接失败时触发URLSessionError。我使用了以下实现
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
guard let error = error as? URLError else { return }
switch error.errorCode {
// offline, timedOut
case -1009, -1001:
delegate?.didDisconnect(
reasonCode: UInt16(URLSessionWebSocketTask.CloseCode.abnormalClosure.rawValue),
error: error)
default: break
}
}
这会在第一个失败的请求发出60秒后触发。设置
URLSessionConfiguration
较短的超时似乎不起作用,它总是在60秒后启动,这很糟糕。希望这有帮助,一个更好的解决方案也会很好。你解决这个问题了吗?已经很久了,我不确定我是否找到了解决办法。不过,我知道没有一个直截了当的“修正”。我相信这就是关于这个问题的文件和我正在进行的项目:请随便看看这个方法是否适合你!错误代码57在enumPOSIXErrorCode
中定义为caseENOTCONN
。当我手动断开websocket任务(如webSocketTask.cancel)时(使用:.goingAway,原因:nil)
,会调用urlSession(…DidCloseWithWith.)
和urlSession(…didCompleteWithError.)
。可能是因为递归函数正在运行。有没有办法优雅地关闭websocketTask?