Issues with URLSessionWebSocketDelegate

Hello, I'm having an unusual problem dealing with web sockets from Swift. I adopted the URLSessionWebSocketDelegate for my session extension and there are times when after the webSocketTask:didOpenWithProtocol: method is called that I then get errors indicating that the web socket is not connected. This all happens in the foreground with airplane mode off, without putting my app in the background.

I get the connection errors simultaneously in 2 places:

  1. urlSession(_ session:task: didCompleteWithError error: )
  2. webSocketTask?.receive(completionHandler: @escaping (Result<URLSessionWebSocketTask.Message, Error>)

Forgive me as I have 2 rather ****** questions:

  1. Is the web socket open state the same as the web socket's connected state?
  2. If it isn't the same how do I know if a web socket is connected, using Apple's URLSessionTask extension?

Thanks. I'd rather stick with Apple's implementation and not use a third party web socket library. Pretty sure the error is mine.

I'd rather stick with Apple's implementation and not use a third party web socket library.

I wholeheartedly endorse that sentiment. Be aware, however, that we offer two WebSocket APIs:

  • NWConnection in Network framework

  • URLSessionWebSocketTask in Foundation

The second is layered on top of the first, and my experience is that the first gives you better facilities to reason about the state of the connection.

Coming back to your specific question:

Is the web socket open state the same as the web socket's connected state?

Yes. URLSession is focused on HTTP where a single request ultimately succeeds or fails, and that error is reported via the did-complete-with-error callback. WebSocket adds the ability to issue multiple reads on the connection, it with its own completion handler. If the underlying connection fails then that’s reported by the did-complete-with-error callback, but each of the pending reads also has to fail by calling its completion handler.

As to what’s going wrong, it’s hard to say without more info. To start, what error do you get?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi Eskimo! Thank you for looking into this, highly appreciated.

I have a session manager that I use for REST calls, and I made the websocket extension a part of that and am using the same session to create the webSocketTask. Was this a bad idea and should I have a separate session altogether for the websocket code?

The error that I'm getting in the completeError method is the following:

2022-01-07 11:07:23 3 - WebSocketExtension in didCompleteWithError Error Domain=NSPOSIXErrorDomain Code=57 "Socket is not connected" UserInfo={NSErrorFailingURLStringKey=https://xxxxx.com/, NSErrorFailingURLKey=https://xxxxx.com/, _NSURLErrorRelatedURLSessionTaskErrorKey=(

    "LocalWebSocketTask <7680DF77-1C5B-46E1-A67D-AB0E0289EC6C>.<6>"

), _NSURLErrorFailingURLSessionTaskErrorKey=LocalWebSocketTask <7680DF77-1C5B-46E1-A67D-AB0E0289EC6C>.<6>}

I get this for the WebSocketTask after the webSocketTask:didOpenWithProtocol: as completed

I also get the same error in the webSocketTask.receive method. Once I get this error in this method, my retry logic in the websockettask.receive() method kicks in and it just makes the problem worse.

Was this a bad idea … ?

Not fundamentally. Indeed, I can see the attraction of this design. While there is a lot of state that can’t be shared between WebSocket and HTTP[S] tasks, there is some stuff, like the TLS session cache, where the sharing might be helpful.

The error that I'm getting …

Is that for every WebSocket task? Or does it crop up intermittently?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

The error that I'm getting …

Is that for every WebSocket task? Or does it crop up intermittently?

I only have one websocket task and it happens intermittently. However when it does happen, it always happens after the webSocketTask:didOpenWithProtocol: has been executed.

The should not happen. is there any way I can check the WebSockeTask at a low level to confirm that the underlying web socket is indeed connected? If I could then I'd be able to trouble shoot this further

is there any way I can check the WebSockeTask at a low level to confirm that the underlying web socket is indeed connected?

You can look at:

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Issues with URLSessionWebSocketDelegate
 
 
Q